Hi Jochen,
Well, I've been slowly making progress on this; kind of feels like bashing my
head against a wall at times, but I have made a small hole in the wall through
which I can see my goal. ;-)
Unfortunately, I've reached a point where the hole isn't getting any bigger and
my google-fu isn't up to the task of finding what I need to make it bigger.
Specifically, I haven't figured out how to inject a variable into the scope of an outer
with's closure that can be used by code in an interior with's closure. For example,
consider
myCtx1.with {
__outerCtx1 = null // injected statement
__currCtx1 = myCtx1 // injected statement
.... some code ...
myCtx2.with {
__outerCtx2 = __currCtx1 // injected statement <--- doesn't work
__currCtx2 = myCtx2 // injected statement
My problem is the compiler chokes on the reference to __currCtx1 in the inner
with closure, claiming that __currCtx1 isn't a property of myCtx1.
My google-fu only tells me I haven't set up the scoping correctly, but for the life of me
I haven't found the correct way to do this. And further experimenting, groping in the
dark, and head banging hasn't helped either. :\
Any illuminating insight, or direction pointing, or example would be greatly appreciated!
Thanks
Ed
On 12/31/2016 06:36 PM, Jochen Theodorou wrote:
>
>
> On 31.12.2016 17:32, Ed Clark wrote:
> [...]
>>> Assuming you still want to do something like this with more... AST
>>> involvement...
>>>
>>>> My questions for you are,
>>>>
>>>> - is an AST the way to go?
>>>
>>> first you have to decide what you want to compile to and then we can
>>> think about how the AST for that has to look like. So this is actually
>>> the last step. But assuming you have some kind of handler object you
>>> could compile a+b to handler.invoke("plus",a,b)... in other words you
>>> would replace almost any expression by a MethodCallExpression. Hint:
>>> ExpressonTransformer and helper classes.
>>
>> Hmmm, I will have a handler object - sort of - and that's the context
>> object itself. Well, at
>> least in the case of instance based contexts. For class based contexts,
>> there won't be
>> an instantiated handler, but I could still see having a static "invoke"
>> method.
>>
>> I hadn't considered the invoke approach; it is interesting. I think it
>> would provide some
>> additional flexibility that the context developer could use to add
>> "operators" beyond the
>> ones built into the Groovy parser/AST. I'll have to think about this
>> some more.
>
> the handler object does not have to be the context object itself. It can be a collection
of
> context objects, be it classes or instances. It could be also be a collection of methods
and
> instances from the context. Important for the compiler part is only the calling convention.
>
>>>> - I'm guessing that I can do the context nesting and composing by building
on
>>>> methodMissing (with ctx2 chaining to ctx3 chaining to Ctx1 above),
but is there
>>>> a better way?
>>>
>>> I guess the code path for categories won´t help you here, since that
>>> is kind of special treated. You could create a special meta class and
>>> all the context methods to it, then use its mechanisms to select an
>>> appropriate method... hint getMetaMethod, init
>>
>> Just to be clear, I don't think there is anything special about the
>> contexts - they are
>> just POGOs. Their methods just happen to be focused on manipulating
>> objects that
>> fall under their scope. So, I'm not sure how creating a meta class
>> would help.
>
> you would not really create a meta class of a specific class, you would create a meta
class in the
> sense of an enumeration of methods and method selection mechanism. But well... now need
for that
> at this point I guess. You can of course simply work with methodMissing.
>
> [...]
>> Yeah, one of my problems is I think too far ahead ;). I start worrying
>> about what
>> it might take to run a marathon when I haven't even learned to walk. So
>> I don't
>> even get started. Part of the this resolution is to just get off my
>> butt and write
>> some code.
>
> that's a good resolution for the new year ;)
>
> Let me help you: assuming you use "with"-blocks:
>
> Step 1) write an AST transformation that will recognize the with-block and store the
context in a
> variable
>
> Step 2) add an expression transformer, that will transform all the expressions of interest
in the
> with-block to method calls based on the context variable
>
> Step 3) implement a context
>
> Step 4) transform nested with method calls to calls that allow you the creation and nesting
of a
> context plus add code to delegate to outer contexts
>
> Even if it turns out not to be useful in the end (and I think it will be useful) you
will still
> get some practice about writing such things. Nothing to really loose here imho ;)
>
> bye Jochen
|