groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ed Clark <>
Subject Re: help with an AST
Date Tue, 14 Feb 2017 11:41:38 GMT
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,

   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!



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
> context objects, be it classes or instances. It could be also be a collection of methods
> 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
>>>>        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

View raw message