Skip to main content

DLR Expression Tree like in Java

Posted by forax on July 31, 2009 at 3:33 PM PDT

Two months ago, I was discussing with a friend about
dynamic languages and JSR 292 when he mentions
DLR Expression Trees.
At that time, I had a vague memory,
mostly because I was under the effect of a
persisting jet lag, when I attend the talk of Mads Torgersen
about it at last year JVM Summit.


By the way, I will attend the next
JVM Summit in September,
I have some good results with
JSR 292 backport.


I had finished the debate with my friend saying that an
expression tree like that can be easily implemented
in one hour on top of JSR 292 API.


In fact, it takes me a little more than one day to just sketch
a prototype. And Yes, I have some free times,
I'm in vacation and my wife allow me to took
my laptop with me :)

An Expression Tree

The main idea is to be able to create an AST and to
transform it into runnable code at runtime.


The following example create a kind of anonymous method
(a lambda, etc) that takes two integers and returns their sum.


The class ExprBuilder use a stack based notation
like by example the
PostScript language
because I'm too lenient to implement a real AST
(with automatic type conversions).

  MethodType methodType = MethodType.make(int.class, int.class, int.class);
   
  ExprBuilder builder = new ExprBuilder(methodType);
  Var a = builder.parameter(0);
  Var b = builder.parameter(1);
  builder.
    load(a).
    load(b).
    add();
   
  MethodHandle mh = builder.createMethodHandle(Main.class);
  System.out.println(mh.invoke(2, 3));

Also notice that createMethodhandle takes a class as argument
because the anonymous method will be able to access to all
fields, methods, etc even if they are declared private
(thanks to the
anonymous class loader)
like a classical member of this class.

If you want to play with it, the code is
available here
and works with current
jdk7 binaries (b67).


Run it with a command line like this one

/usr/jdk/jdk1.7.0/bin/java -cp classes:lib/asm-all-3.2.jar -XX:+EnableInvokeDynamic Main

Cheers,

Rémi

Related Topics >>

Comments

As far as I can see you are using asm bytecode manipulation library to create some bytecode on the fly. Please correct me if I am wrong. Tha is why it looks to me like this is not very "clean" and "true" implementation of Expression Tree using jdk 7 features. For me it is some sort of "simulation" which requires non standard and non-trivial hacks like bytecode manipulation.

Better later than never... @aberrant, it's not closure by example you can't capture a field, so it's more a lambda generator using method handle (not invokedynamic). You're right that it allows a kind of method (or function) injection. @4bugzilla, you are right, I use ASM. It's as clean as DLR expression tree implementation which heavily relies on namespace System.Reflection.Emit. I agree that bytecode manipulation is not standard, there is no package java.reflection.emit in jdk7 but it's fairly usual, in jdk7, reflection use bytecode generation to speed up method invocation, implement java.lang.reflect.Proxy or to speed up XSLT transformation. Also Hibernate or Toplink use bytecode manipulation. At last, in this example, the bytecode generator is fairly trivial. Rémi

Wait.. did you just implement a simple closure/lambda using invokedynamic? Or is this more of a mixin/method injection example? I don't quite understand all of it yet but it looks interesting.