groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jochen Theodorou <blackd...@gmx.org>
Subject Re: help with an AST
Date Fri, 30 Dec 2016 20:20:56 GMT
Hi Ed,

I am wondering if categories would actually do what you want already 
without touching the AST. Groovy Categories are actually no syntactic 
construct and their scope is not lexical (thread local instead)... but maybe

Let us assume you have two Strings obj1 and obj2, then you can define a 
category:

class StringCategory {
   static String plus(String obj1, String obj2) { "from StringCategory 
$obj1 $obj2" }
}

and code like this:

use (StringCategory) {
   assert "a"+"b" == "from StringCategory a b"
}

the construct supports nesting from inside out, that means the inner 
context wins over the outer context and the rightmost over the leftmost.

What this does not support is an instance based context.

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.

>      - 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


>      - what might I be breaking in Groovy by doing this?

that depends on how you do it.

>      - what help/hints can I get from the compiler vs. doing this all at runtime?

worry about such things once you have come up with something that works ;)

original mail:
On 30.12.2016 20:02, Ed Clark wrote:
> Happy New Year All!
>
> As one of my New Year's resolutions, I'm going to try and implement a
> programming
> construct that I've been want to play with for a while - and I think a
> Groovy AST just
> might let me do it.
>
> While the syntax part of this is straightforward (I think), I'm not as
> clear on the
> how of the method resolution logic that will be at the core.
>
> The basic idea is that I'll be able to designate a section of code where
> binary
> operators would be resolved not against the neighbouring object's class,
> but against
> the surrounding context.  Perhaps some code will make my goal clearer....
>
> My understanding of Groovy (and OO in general) is that an expression like
>      obj1 + obj2
> is interpreted as if it were written
>      obj1.plus( obj2)
>
> What I'd like to do is have something like
>      withCtx( ctx1) {
>          obj1 + obj2
>      }
> get interpreted as
>      ctx1.plus( obj1, obj2)
>
>
> If I squint at this, it kind of sort of looks to me a bit like how the
> "with" construct
> in Groovy works.  But, the with construct is an enhancement to the
> existing OO
> method resolution; this construct would go in a different direction.
>
> (Actually, to be useful, the interior expression would probably be
> something
> like -- var1 = obj1 + obj2 -- but I want to focus on one step/method at
> a time.)
>
> With this idea, methods between objects (e.g. binary methods) don't
> belong to the
> class of (one of the) objects involved, but to the context within which
> the objects
> are being used.
>
> And, just to make things more challenging, I'd like to be able to nest
> and compose
> contexts.
>
> Consider
>      withCtx( Ctx1) {
>          withCtx( ctx2, ctx3) {
>              obj1 + obj2
>          }
>      }
>
> Here, the methods of ctx2 would be checked to see if there's a "plus"
> that can take
> arguments obj1 and obj2.  If not, then ctx3's methods will be check.  If
> there's no
> appropriate "plus" in ctx3, then Ctx1's methods will be checked.
>
> Finally, if there are no appropriate context methods for "plus-ing"
> these two
> objects, then method resolution would fall back to the normal Groovy
> approach.
>
> To add yet another wrinkle, I'd like to be able to use either a Context
> class or a context
> instance when doing this.  So, in the above, if "Ctx1" is a class name
> (note the cap C),
> its static methods would be used.  But, assuming ctx2 and ctx3 are
> context instances
> (note the lower case c's), the appropriate instance methods would be used.
>
> Hopefully this description makes my goal clearer.
>
> My questions for you are,
>
>      - is an AST the way to go?
>
>      - 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?
>
>      - what might I be breaking in Groovy by doing this?
>
>      - what help/hints can I get from the compiler vs. doing this all at
> runtime?
>
>
> Thanks for your time,
>
> Ed Clark


Mime
View raw message