changeset 19283:08aa0372dad4

Truffle-DSL: implement new guard expression syntax.
author Christian Humer <christian.humer@gmail.com>
date Fri, 23 Jan 2015 02:55:23 +0100
parents ae81dd154fb6
children b339d723a06b
files graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Copyright.frame graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpression.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Expression.atg graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/InvalidExpressionException.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.frame graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.frame graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/DSLExpressionGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AssumptionExpression.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CacheExpression.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java
diffstat 40 files changed, 2992 insertions(+), 628 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java	Fri Jan 23 02:55:23 2015 +0100
@@ -51,11 +51,11 @@
             return true;
         }
 
-        @Specialization(guards = {"guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1",
-                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2",
-                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1",
-                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2",
-                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1"})
+        @Specialization(guards = {"guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1()",
+                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2()",
+                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1()",
+                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2()",
+                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1()"})
         public int execute() {
             return 42;
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java	Fri Jan 23 02:55:23 2015 +0100
@@ -100,7 +100,7 @@
             return a == 0;
         }
 
-        @Specialization(guards = "isZero")
+        @Specialization(guards = "isZero(a)")
         int f1(int a) {
             return a + 1;
         }
@@ -142,17 +142,17 @@
             return a > 0;
         }
 
-        @Implies("isGreaterZero")
+        @Implies("isGreaterZero(a)")
         static boolean isOne(int a) {
             return a == 1;
         }
 
-        @Specialization(guards = {"isOne"})
+        @Specialization(guards = {"isOne(a)"})
         int f1(int a) {
             return a + 1;
         }
 
-        @Specialization(contains = "f1", guards = {"isGreaterZero"})
+        @Specialization(contains = "f1", guards = {"isGreaterZero(a)"})
         int f2(int a) {
             if (a == 1) {
                 return 2;
@@ -190,21 +190,17 @@
     @NodeChild("a")
     abstract static class Contains4 extends ValueNode {
 
-        static boolean isGreaterEqualZero(int a) {
-            return a >= 0;
-        }
-
         @Implies("isGreaterEqualZero")
         static boolean isOne(int a) {
             return a == 1;
         }
 
-        @Specialization(guards = {"isOne"})
+        @Specialization(guards = "isOne(a)")
         int f0(int a) {
             return 1;
         }
 
-        @Specialization(contains = "f0", guards = {"isGreaterEqualZero"})
+        @Specialization(contains = "f0", guards = "a >= 0")
         int f1(int a) {
             return a;
         }
@@ -329,7 +325,7 @@
             return a;
         }
 
-        @ExpectError({"Specialization is not reachable. It is shadowed by f0(double).", "The contained specialization 'f0' is not fully compatible.%"})
+        @ExpectError({"Specialization is not reachable. It is shadowed by f0(double)."})
         @Specialization(contains = "f0")
         int f1(int a) { // implicit type
             return a;
@@ -343,7 +339,6 @@
             return a;
         }
 
-        @ExpectError("The contained specialization 'f0' is not fully compatible.%")
         @Specialization(contains = "f0")
         Object f1(int a, Object b) {
             return a;
@@ -357,7 +352,6 @@
             return a;
         }
 
-        @ExpectError("The contained specialization 'f0' is not fully compatible.%")
         @Specialization(contains = "f0")
         Object f1(int a, double b) { // implicit type
             return a;
@@ -370,7 +364,7 @@
             return true;
         }
 
-        @Specialization(guards = "g1")
+        @Specialization(guards = "g1()")
         Object f0() {
             return null;
         }
@@ -392,8 +386,8 @@
             return null;
         }
 
-        @ExpectError({"Specialization is not reachable. It is shadowed by f0().", "The contained specialization 'f0' is not fully compatible.%"})
-        @Specialization(guards = "g1", contains = "f0")
+        @ExpectError({"Specialization is not reachable. It is shadowed by f0()."})
+        @Specialization(guards = "g1()", contains = "f0")
         Object f1() {
             return null;
         }
@@ -405,13 +399,12 @@
             return true;
         }
 
-        @Specialization(guards = "g1")
+        @Specialization(guards = "g1()")
         Object f0() {
             return null;
         }
 
-        @ExpectError({"The contained specialization 'f0' is not fully compatible.%"})
-        @Specialization(guards = "!g1", contains = "f0")
+        @Specialization(guards = "!g1()", contains = "f0")
         Object f1() {
             return null;
         }
@@ -427,13 +420,12 @@
             return true;
         }
 
-        @Specialization(guards = "g1")
+        @Specialization(guards = "g1()")
         Object f0() {
             return null;
         }
 
-        @ExpectError({"The contained specialization 'f0' is not fully compatible.%"})
-        @Specialization(guards = "g2", contains = "f0")
+        @Specialization(guards = "g2()", contains = "f0")
         Object f1() {
             return null;
         }
@@ -450,12 +442,12 @@
             return true;
         }
 
-        @Specialization(guards = "g1")
+        @Specialization(guards = "g1()")
         Object f0() {
             return null;
         }
 
-        @Specialization(guards = "g2", contains = "f0")
+        @Specialization(guards = "g2()", contains = "f0")
         Object f1() {
             return null;
         }
@@ -472,12 +464,12 @@
             return true;
         }
 
-        @Specialization(guards = "g1")
+        @Specialization(guards = "g1()")
         Object f0() {
             return null;
         }
 
-        @Specialization(guards = "!g2", contains = "f0")
+        @Specialization(guards = "!g2()", contains = "f0")
         Object f1() {
             return null;
         }
@@ -493,12 +485,12 @@
             return true;
         }
 
-        @Specialization(guards = {"g1", "g2"})
+        @Specialization(guards = {"g1()", "g2()"})
         Object f0() {
             return null;
         }
 
-        @Specialization(guards = "g2", contains = "f0")
+        @Specialization(guards = "g2()", contains = "f0")
         Object f1() {
             return null;
         }
@@ -518,36 +510,6 @@
         }
     }
 
-    @NodeAssumptions("a1")
-    abstract static class ContainsAssumption2 extends ValueNode {
-
-        @Specialization
-        Object f0() {
-            return null;
-        }
-
-        @ExpectError({"Specialization is not reachable. It is shadowed by f0().", "The contained specialization 'f0' is not fully compatible.%"})
-        @Specialization(contains = "f0", assumptions = "a1")
-        Object f1() {
-            return null;
-        }
-    }
-
-    @NodeAssumptions({"a1", "a2"})
-    abstract static class ContainsAssumption3 extends ValueNode {
-
-        @Specialization(assumptions = "a1")
-        Object f0() {
-            return null;
-        }
-
-        @ExpectError({"The contained specialization 'f0' is not fully compatible.%"})
-        @Specialization(contains = "f0", assumptions = "a2")
-        Object f1() {
-            return null;
-        }
-    }
-
     @NodeAssumptions({"a1", "a2"})
     abstract static class ContainsAssumption4 extends ValueNode {
 
@@ -619,20 +581,12 @@
     @NodeChild("a")
     static class PolymorphicToMonomorphic0 extends ValueNode {
 
-        boolean isOne(int a) {
-            return a == 1;
-        }
-
-        boolean isTwo(int a) {
-            return a == 2;
-        }
-
-        @Specialization(guards = "isOne")
+        @Specialization(guards = "a == 1")
         int do1(int a) {
             return a;
         }
 
-        @Specialization(guards = "isTwo")
+        @Specialization(guards = "a == 2")
         int do2(int a) {
             return a;
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java	Fri Jan 23 02:55:23 2015 +0100
@@ -104,7 +104,7 @@
             return "(int)";
         }
 
-        @Specialization(guards = "notInt")
+        @Specialization(guards = "notInt(a)")
         String f2(Object a) {
             return "(object)";
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java	Fri Jan 23 02:55:23 2015 +0100
@@ -36,7 +36,7 @@
     @NodeChild("a")
     static class ImportGuards0 extends ValueNode {
 
-        @Specialization(guards = "staticGuard")
+        @Specialization(guards = "staticGuard(a)")
         int f0(int a) {
             return a;
         }
@@ -46,26 +46,26 @@
     @ImportGuards(Imports0.class)
     static class ImportGuards1 extends ValueNode {
 
-        @ExpectError("No compatible guard with method name 'nonStaticGuard' found.")
-        @Specialization(guards = "nonStaticGuard")
+        @ExpectError("Error parsing expression 'nonStaticGuard(a)': The method nonStaticGuard is undefined for the enclosing scope.")
+        @Specialization(guards = "nonStaticGuard(a)")
         int f1(int a) {
             return a;
         }
 
-        @ExpectError("No compatible guard with method name 'protectedGuard' found.")
-        @Specialization(guards = "protectedGuard")
+        @ExpectError("Error parsing expression 'protectedGuard(a)': The method protectedGuard is undefined for the enclosing scope.")
+        @Specialization(guards = "protectedGuard(a)")
         int f2(int a) {
             return a;
         }
 
-        @ExpectError("No compatible guard with method name 'packageGuard' found.")
-        @Specialization(guards = "packageGuard")
+        @ExpectError("Error parsing expression 'packageGuard(a)': The method packageGuard is undefined for the enclosing scope.")
+        @Specialization(guards = "packageGuard(a)")
         int f3(int a) {
             return a;
         }
 
-        @ExpectError("No compatible guard with method name 'privateGuard' found.")
-        @Specialization(guards = "privateGuard")
+        @ExpectError("Error parsing expression 'privateGuard(a)': The method privateGuard is undefined for the enclosing scope.")
+        @Specialization(guards = "privateGuard(a)")
         int f4(int a) {
             return a;
         }
@@ -159,7 +159,7 @@
             return a == 1;
         }
 
-        @Specialization(guards = "staticGuard")
+        @Specialization(guards = "staticGuard(a)")
         int f0(int a) {
             return a;
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java	Fri Jan 23 02:55:23 2015 +0100
@@ -30,20 +30,12 @@
     @NodeChild("a")
     static class InsertBefore1Base extends ValueNode {
 
-        boolean g1(int a) {
-            return a == 1;
-        }
-
-        boolean g2(int a) {
-            return a == 2;
-        }
-
-        @Specialization(guards = "g1")
+        @Specialization(guards = "a == 1")
         int f1(int a) {
             return a;
         }
 
-        @Specialization(guards = "g2")
+        @Specialization(guards = "a == 2")
         int f3(int a) {
             return a;
         }
@@ -63,11 +55,7 @@
     @NodeChild("a")
     static class InsertBefore1T2 extends InsertBefore1Base {
 
-        boolean g0(int a) {
-            return a == 0;
-        }
-
-        @Specialization(guards = "g0", insertBefore = "f1")
+        @Specialization(guards = "a == 0", insertBefore = "f1")
         int f0(int a) {
             return a;
         }
@@ -77,11 +65,7 @@
     @NodeChild("a")
     static class InsertBefore1T3 extends InsertBefore1Base {
 
-        boolean g0(int a) {
-            return a == 0;
-        }
-
-        @Specialization(guards = "g0", insertBefore = "f3")
+        @Specialization(guards = "a == 0", insertBefore = "f3")
         int f0(int a) {
             return a;
         }
@@ -93,10 +77,6 @@
                     "Method f1(int) at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int)."})
     static class InsertBefore1T4 extends InsertBefore1Base {
 
-        boolean g0(int a) {
-            return a == 0;
-        }
-
         @Specialization(insertBefore = "f1")
         int f0(int a) {
             return a;
@@ -126,7 +106,7 @@
             return a == 0;
         }
 
-        @Specialization(insertBefore = "f1", guards = "g0")
+        @Specialization(insertBefore = "f1", guards = "a == 0")
         int f0(int a) {
             return a;
         }
@@ -136,11 +116,7 @@
     @NodeChild("a")
     static class InsertBefore1T6part2 extends InsertBefore1T6part1 {
 
-        boolean g(int a) {
-            return a == 0;
-        }
-
-        @Specialization(insertBefore = "f0", guards = "g")
+        @Specialization(insertBefore = "f0", guards = "a == 3")
         int f(int a) {
             return a;
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java	Fri Jan 23 02:55:23 2015 +0100
@@ -72,7 +72,7 @@
             return value0 != Integer.MAX_VALUE;
         }
 
-        @Specialization(guards = "g")
+        @Specialization(guards = "g(value0)")
         int f1(int value0) {
             specializedInvocations++;
             return value0 + 1;
@@ -107,7 +107,7 @@
             return globalFlag;
         }
 
-        @Specialization(guards = "globalFlagGuard")
+        @Specialization(guards = "globalFlagGuard()")
         int f1(Object value0) {
             return 41;
         }
@@ -132,7 +132,7 @@
             return true;
         }
 
-        @Specialization(guards = "baseGuard")
+        @Specialization(guards = "baseGuard(value0)")
         int doSpecialized(BExtendsAbstract value0) {
             return 42;
         }
@@ -145,8 +145,7 @@
             return true;
         }
 
-        @Specialization(guards = "baseGuard")
-        @ExpectError("No guard with name 'baseGuard' matched the required signature.%")
+        @Specialization(guards = "baseGuard(value0)")
         int doSpecialized(String value0) {
             return 42;
         }
@@ -166,7 +165,7 @@
             return true;
         }
 
-        @Specialization(guards = "baseGuard")
+        @Specialization(guards = "baseGuard(value0)")
         int doSpecialized(int value0) {
             return value0;
         }
@@ -186,7 +185,7 @@
             return true;
         }
 
-        @Specialization(guards = "baseGuard")
+        @Specialization(guards = "baseGuard(value0)")
         int doSpecialized(int value0) {
             return value0;
         }
@@ -210,7 +209,7 @@
             return true;
         }
 
-        @Specialization(guards = "guard")
+        @Specialization(guards = "guard(value0)")
         int doSpecialized(int value0) {
             return value0;
         }
@@ -233,7 +232,7 @@
             return true;
         }
 
-        @Specialization(guards = "guard")
+        @Specialization(guards = "guard(value0)")
         int doSpecialized(BExtendsAbstract value0) {
             return 42;
         }
@@ -261,7 +260,7 @@
             return true;
         }
 
-        @Specialization(guards = "guard")
+        @Specialization(guards = "guard(value0)")
         int doSpecialized(BExtendsAbstract value0) {
             return 42;
         }
@@ -274,7 +273,7 @@
             return false;
         }
 
-        @Specialization(guards = "guard")
+        @Specialization(guards = "guard(value0)")
         int doSpecialized(BExtendsAbstract value0) {
             return 42;
         }
@@ -283,7 +282,7 @@
     @NodeChildren({@NodeChild("a"), @NodeChild("b")})
     abstract static class TestGuardResolve5 extends ValueNode {
 
-        @Specialization(guards = "guard")
+        @Specialization(guards = "guard(left, right)")
         int add(Interface left, Interface right) {
             return 42;
         }
@@ -308,12 +307,12 @@
             return true;
         }
 
-        @Specialization(guards = "guard")
+        @Specialization(guards = "guard(value0)")
         BExtendsAbstract do1(BExtendsAbstract value0) {
             return value0;
         }
 
-        @Specialization(guards = "guard")
+        @Specialization(guards = "guard(value0)")
         CExtendsAbstract do2(CExtendsAbstract value0) {
             return value0;
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java	Fri Jan 23 02:55:23 2015 +0100
@@ -69,7 +69,7 @@
             return true;
         }
 
-        @Specialization(guards = "guard ()")
+        @Specialization(guards = "guard()")
         int do1() {
             return 42;
         }
@@ -214,7 +214,7 @@
             return true;
         }
 
-        @ExpectError("No compatible guard with method name 'guard(' found.%")
+        @ExpectError("Error parsing expression 'guard(': -- line 1 col 7: \")\" expected%")
         @Specialization(guards = "guard(")
         int do1() {
             return 42;
@@ -227,7 +227,7 @@
             return true;
         }
 
-        @ExpectError("No compatible guard with method name 'guard)' found.%")
+        @ExpectError("Error parsing expression 'guard)': -- line 1 col 6: EOF expected%")
         @Specialization(guards = "guard)")
         int do1() {
             return 42;
@@ -241,7 +241,7 @@
             return true;
         }
 
-        @ExpectError("Guard parameter 'a' for guard 'guard' could not be mapped to a declared child node.")
+        @ExpectError("Error parsing expression 'guard(a)': a cannot be resolved.")
         @Specialization(guards = "guard(a)")
         int do1() {
             return 42;
@@ -255,7 +255,7 @@
             return true;
         }
 
-        @ExpectError("Guard parameter 'a' for guard 'guard' could not be mapped to a declared child node.")
+        @ExpectError("Error parsing expression 'guard(a)': a cannot be resolved.")
         @Specialization(guards = "guard(a)")
         int do1(int b) {
             return b;
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java	Fri Jan 23 02:55:23 2015 +0100
@@ -45,7 +45,7 @@
             return true;
         }
 
-        @Specialization(guards = "!guard")
+        @Specialization(guards = "!guard()")
         int do1() {
             throw new AssertionError();
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java	Fri Jan 23 02:55:23 2015 +0100
@@ -182,7 +182,7 @@
             return false;
         }
 
-        @Specialization(guards = "foo")
+        @Specialization(guards = "foo()")
         int do2() {
             return 1;
         }
@@ -206,7 +206,7 @@
         }
 
         @ExpectError("Specialization is not reachable. It is shadowed by do2().")
-        @Specialization(guards = "foo")
+        @Specialization(guards = "foo()")
         int do1() {
             return 1;
         }
@@ -219,7 +219,7 @@
             return false;
         }
 
-        @Specialization(guards = "foo")
+        @Specialization(guards = "foo()")
         int do2() {
             return 1;
         }
@@ -237,13 +237,13 @@
             return false;
         }
 
-        @Specialization(guards = "foo")
+        @Specialization(guards = "foo()")
         int do2() {
             return 1;
         }
 
         @ExpectError("Specialization is not reachable. It is shadowed by do2().")
-        @Specialization(guards = "foo")
+        @Specialization(guards = "foo()")
         int do1() {
             return 2;
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java	Fri Jan 23 02:55:23 2015 +0100
@@ -119,7 +119,7 @@
             return false;
         }
 
-        @Specialization(guards = "guard")
+        @Specialization(guards = "guard(a, hasB, b)")
         int doIt(int a, boolean hasB, int b) {
             return a + b;
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java	Fri Jan 23 02:55:23 2015 +0100
@@ -74,29 +74,17 @@
     @NodeChild("a")
     static class SourceSection0 extends ValueNode {
 
-        boolean isOne(int a) {
-            return a == 1;
-        }
-
-        boolean isTwo(int a) {
-            return a == 2;
-        }
-
-        boolean isThree(int a) {
-            return a == 3;
-        }
-
-        @Specialization(guards = "isOne")
+        @Specialization(guards = "a == 1")
         int do1(int a) {
             return a;
         }
 
-        @Specialization(guards = "isTwo")
+        @Specialization(guards = "a == 2")
         int do2(int a) {
             return a;
         }
 
-        @Specialization(guards = "isThree")
+        @Specialization(guards = "a == 3")
         int do3(int a) {
             return a;
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java	Fri Jan 23 02:55:23 2015 +0100
@@ -212,7 +212,7 @@
             return a == 1;
         }
 
-        @Specialization(guards = "guard0")
+        @Specialization(guards = "guard0(a)")
         int do2(int a) {
             return a;
         }
@@ -309,7 +309,7 @@
 
         static int fallthrough1;
 
-        @Specialization(guards = "isDo1", rewriteOn = ArithmeticException.class)
+        @Specialization(guards = "isDo1(a)", rewriteOn = ArithmeticException.class)
         int do1(int a) throws ArithmeticException {
             if (a == 0) {
                 fallthrough1++;
@@ -322,7 +322,7 @@
             return a == 0 || a == 1;
         }
 
-        @Specialization(guards = "isDo1")
+        @Specialization(guards = "isDo1(a)")
         int do2(int a) {
             return a;
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java	Fri Jan 23 02:55:23 2015 +0100
@@ -58,9 +58,9 @@
         TestGrouping.true3 = 0;
 
         Assert.assertEquals(42, TestHelper.executeWith(root, 21, 21));
-        Assert.assertEquals(4, TestGrouping.true1);
+        Assert.assertEquals(5, TestGrouping.true1);
         Assert.assertEquals(0, TestGrouping.false1);
-        Assert.assertEquals(4, TestGrouping.true2);
+        Assert.assertEquals(5, TestGrouping.true2);
         Assert.assertEquals(5, TestGrouping.false2);
         Assert.assertEquals(5, TestGrouping.true3);
         Assert.assertEquals(10, SimpleTypes.intCheck);
@@ -69,9 +69,9 @@
         Assert.assertEquals(4, a3.checked);
 
         Assert.assertEquals(42, TestHelper.executeWith(root, 21, 21));
-        Assert.assertEquals(5, TestGrouping.true1);
+        Assert.assertEquals(6, TestGrouping.true1);
         Assert.assertEquals(0, TestGrouping.false1);
-        Assert.assertEquals(5, TestGrouping.true2);
+        Assert.assertEquals(6, TestGrouping.true2);
         Assert.assertEquals(6, TestGrouping.false2);
         Assert.assertEquals(6, TestGrouping.true3);
 
@@ -123,32 +123,32 @@
             throw new AssertionError();
         }
 
-        @Specialization(guards = {"true1", "true2", "!false2", "true3"}, assumptions = {"a1", "a3"}, rewriteOn = RuntimeException.class)
+        @Specialization(guards = {"true1(value1)", "true2(value1)", "!false2(value1)", "true3(value1)"}, assumptions = {"a1", "a3"}, rewriteOn = RuntimeException.class)
         public int throwRewrite(int value1, int value2) {
             throw new RuntimeException();
         }
 
-        @Specialization(guards = {"true1", "true2", "!false2", "true3"}, contains = "throwRewrite", assumptions = {"a1", "a3"})
+        @Specialization(guards = {"true1(value1)", "true2(value1)", "!false2(value1)", "true3(value1)"}, contains = "throwRewrite", assumptions = {"a1", "a3"})
         public int success(int value1, int value2) {
             return value1 + value2;
         }
 
-        @Specialization(guards = {"true1", "true2", "!false2", "!true3"}, assumptions = {"a1", "a3"})
+        @Specialization(guards = {"true1(value1)", "true2(value1)", "!false2(value1)", "!true3(value1)"}, assumptions = {"a1", "a3"})
         public int fail5(int value1, int value2) {
             throw new AssertionError();
         }
 
-        @Specialization(guards = {"true1", "true2", "false2"}, assumptions = {"a1", "a3"})
+        @Specialization(guards = {"true1(value1)", "true2(value1)", "false2(value1)"}, assumptions = {"a1", "a3"})
         public int fail4(int value1, int value2) {
             throw new AssertionError();
         }
 
-        @Specialization(guards = {"true1", "true2"}, assumptions = {"a1", "a3"})
+        @Specialization(guards = {"true1(value1)", "true2(value1)"}, assumptions = {"a1", "a3"})
         public int fail2break(int value1, int value2) {
             throw new AssertionError();
         }
 
-        @Specialization(guards = {"true1", "false1"})
+        @Specialization(guards = {"true1(value1)", "false1(value1, value2)"})
         public int fail1(int value1, int value2) {
             throw new AssertionError();
         }
@@ -165,17 +165,17 @@
     @NodeChild(value = "genericChild", type = GenericInt.class)
     public abstract static class TestElseConnectionBug1 extends ValueNode {
 
-        @Specialization(rewriteOn = {SlowPathException.class}, guards = "isInitialized")
+        @Specialization(rewriteOn = {SlowPathException.class}, guards = "isInitialized(value)")
         public int do1(int value) throws SlowPathException {
             throw new SlowPathException();
         }
 
-        @Specialization(contains = "do1", guards = "isInitialized")
+        @Specialization(contains = "do1", guards = "isInitialized(value)")
         public int do2(int value) {
             return value == 42 ? value : 0;
         }
 
-        @Specialization(guards = "!isInitialized")
+        @Specialization(guards = "!isInitialized(value)")
         public Object do3(int value) {
             throw new AssertionError();
         }
@@ -208,17 +208,17 @@
     @NodeChild
     public abstract static class TestElseConnectionBug2 extends ValueNode {
 
-        @Specialization(guards = "guard0")
+        @Specialization(guards = "guard0(value)")
         public int do1(int value) {
             throw new AssertionError();
         }
 
-        @Specialization(guards = "guard1")
+        @Specialization(guards = "guard1(value)")
         public int do2(int value) {
             throw new AssertionError();
         }
 
-        @Specialization(guards = "!guard0")
+        @Specialization(guards = "!guard0(value)")
         public int do3(int value) {
             return value;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Copyright.frame	Fri Jan 23 02:55:23 2015 +0100
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// The content of this file is automatically generated. DO NOT EDIT.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpression.java	Fri Jan 23 02:55:23 2015 +0100
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.expression;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public abstract class DSLExpression {
+
+    private DSLExpression() {
+    }
+
+    public static DSLExpression parse(String input) {
+        return Parser.parse(input);
+    }
+
+    public final List<Variable> findBoundVariables() {
+        final List<Variable> variables = new ArrayList<>();
+        this.accept(new AbstractDSLExpressionVisitor() {
+
+            @Override
+            public void visitVariable(Variable variable) {
+                if (variable.getReceiver() == null) {
+                    variables.add(variable);
+                }
+            }
+
+        });
+        return variables;
+    }
+
+    public final boolean isVariableBound(VariableElement variableElement) {
+        for (Variable variable : findBoundVariables()) {
+            if (variable.getResolvedVariable() == variableElement) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public abstract TypeMirror getResolvedType();
+
+    public abstract void accept(DSLExpressionVisitor visitor);
+
+    public static final class Negate extends DSLExpression {
+
+        private final DSLExpression receiver;
+
+        public Negate(DSLExpression receiver) {
+            this.receiver = receiver;
+        }
+
+        @Override
+        public void accept(DSLExpressionVisitor visitor) {
+            receiver.accept(visitor);
+            visitor.visitNegate(this);
+        }
+
+        public DSLExpression getReceiver() {
+            return receiver;
+        }
+
+        @Override
+        public TypeMirror getResolvedType() {
+            return receiver.getResolvedType();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Negate) {
+                return receiver.equals(((Negate) obj).receiver);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return receiver.hashCode();
+        }
+    }
+
+    public static final class Binary extends DSLExpression {
+
+        private final String operator;
+        private final DSLExpression left;
+        private final DSLExpression right;
+
+        private TypeMirror resolvedType;
+
+        public Binary(String operator, DSLExpression left, DSLExpression right) {
+            this.operator = operator;
+            this.left = left;
+            this.right = right;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Binary) {
+                Binary other = (Binary) obj;
+                return operator.equals(other.operator) && left.equals(other.left) && right.equals(other.right);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(operator, left, right);
+        }
+
+        public String getOperator() {
+            return operator;
+        }
+
+        public DSLExpression getLeft() {
+            return left;
+        }
+
+        public DSLExpression getRight() {
+            return right;
+        }
+
+        @Override
+        public void accept(DSLExpressionVisitor visitor) {
+            left.accept(visitor);
+            right.accept(visitor);
+            visitor.visitBinary(this);
+        }
+
+        @Override
+        public TypeMirror getResolvedType() {
+            return resolvedType;
+        }
+
+        public void setResolvedType(TypeMirror resolvedType) {
+            this.resolvedType = resolvedType;
+        }
+
+        @Override
+        public String toString() {
+            return "Binary [left=" + left + ", operator=" + operator + ", right=" + right + ", resolvedType=" + resolvedType + "]";
+        }
+
+    }
+
+    public static final class Call extends DSLExpression {
+
+        private final DSLExpression receiver;
+        private final String name;
+        private final List<DSLExpression> parameters;
+
+        private ExecutableElement resolvedMethod;
+
+        public Call(DSLExpression receiver, String name, List<DSLExpression> parameters) {
+            this.receiver = receiver;
+            this.name = name;
+            this.parameters = parameters;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Call) {
+                Call other = (Call) obj;
+                return Objects.equals(receiver, other.receiver) && name.equals(other.name) && parameters.equals(other.parameters);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(receiver, name, parameters);
+        }
+
+        public DSLExpression getReceiver() {
+            return receiver;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public List<DSLExpression> getParameters() {
+            return parameters;
+        }
+
+        @Override
+        public void accept(DSLExpressionVisitor visitor) {
+            if (receiver != null) {
+                receiver.accept(visitor);
+            }
+            for (DSLExpression parameter : getParameters()) {
+                parameter.accept(visitor);
+            }
+            visitor.visitCall(this);
+        }
+
+        @Override
+        public TypeMirror getResolvedType() {
+            return resolvedMethod != null ? resolvedMethod.getReturnType() : null;
+        }
+
+        public ExecutableElement getResolvedMethod() {
+            return resolvedMethod;
+        }
+
+        public void setResolvedMethod(ExecutableElement resolvedMethod) {
+            this.resolvedMethod = resolvedMethod;
+        }
+
+        @Override
+        public String toString() {
+            return "Call [receiver=" + receiver + ", name=" + name + ", parameters=" + parameters + ", resolvedMethod=" + resolvedMethod + "]";
+        }
+
+    }
+
+    public static final class Variable extends DSLExpression {
+
+        private final DSLExpression receiver;
+        private final String name;
+
+        private VariableElement resolvedVariable;
+
+        public Variable(DSLExpression receiver, String name) {
+            this.receiver = receiver;
+            this.name = name;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Variable) {
+                Variable other = (Variable) obj;
+                return Objects.equals(receiver, other.receiver) && name.equals(other.name);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(receiver, name);
+        }
+
+        public DSLExpression getReceiver() {
+            return receiver;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public void accept(DSLExpressionVisitor visitor) {
+            if (receiver != null) {
+                receiver.accept(visitor);
+            }
+            visitor.visitVariable(this);
+        }
+
+        @Override
+        public TypeMirror getResolvedType() {
+            return resolvedVariable != null ? resolvedVariable.asType() : null;
+        }
+
+        public void setResolvedVariable(VariableElement resolvedVariable) {
+            this.resolvedVariable = resolvedVariable;
+        }
+
+        public VariableElement getResolvedVariable() {
+            return resolvedVariable;
+        }
+
+        @Override
+        public String toString() {
+            return "Variable [receiver=" + receiver + ", name=" + name + ", resolvedVariable=" + resolvedVariable + "]";
+        }
+
+    }
+
+    public static final class IntLiteral extends DSLExpression {
+
+        private final String literal;
+
+        private int resolvedValueInt;
+        private TypeMirror resolvedType;
+
+        public IntLiteral(String literal) {
+            this.literal = literal;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof IntLiteral) {
+                IntLiteral other = (IntLiteral) obj;
+                return resolvedValueInt == other.resolvedValueInt;
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return resolvedValueInt;
+        }
+
+        public String getLiteral() {
+            return literal;
+        }
+
+        public int getResolvedValueInt() {
+            return resolvedValueInt;
+        }
+
+        public void setResolvedValueInt(int resolved) {
+            this.resolvedValueInt = resolved;
+        }
+
+        @Override
+        public TypeMirror getResolvedType() {
+            return resolvedType;
+        }
+
+        public void setResolvedType(TypeMirror resolvedType) {
+            this.resolvedType = resolvedType;
+        }
+
+        @Override
+        public void accept(DSLExpressionVisitor visitor) {
+            visitor.visitIntLiteral(this);
+        }
+
+        @Override
+        public String toString() {
+            return "IntLiteral [literal=" + literal + ", resolvedValueInt=" + resolvedValueInt + ", resolvedType=" + resolvedType + "]";
+        }
+
+    }
+
+    public abstract class AbstractDSLExpressionVisitor implements DSLExpressionVisitor {
+
+        public void visitBinary(Binary binary) {
+        }
+
+        public void visitCall(Call binary) {
+        }
+
+        public void visitIntLiteral(IntLiteral binary) {
+        }
+
+        public void visitNegate(Negate negate) {
+        }
+
+        public void visitVariable(Variable binary) {
+        }
+    }
+
+    public interface DSLExpressionVisitor {
+
+        void visitBinary(Binary binary);
+
+        void visitNegate(Negate negate);
+
+        void visitCall(Call binary);
+
+        void visitVariable(Variable binary);
+
+        void visitIntLiteral(IntLiteral binary);
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java	Fri Jan 23 02:55:23 2015 +0100
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.expression;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Binary;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Call;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.DSLExpressionVisitor;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.IntLiteral;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public class DSLExpressionResolver implements DSLExpressionVisitor {
+
+    private static final List<String> LOGIC_OPERATORS = Arrays.asList("||");
+    private static final List<String> COMPARABLE_OPERATORS = Arrays.asList("<", "<=", ">", ">=");
+    private static final List<String> IDENTITY_OPERATORS = Arrays.asList("==", "!=");
+    private static final String CONSTRUCTOR_KEYWORD = "new";
+
+    private List<VariableElement> variables;
+    private List<ExecutableElement> methods;
+    private final ProcessorContext context;
+
+    public DSLExpressionResolver(ProcessorContext context, List<? extends Element> lookupElements) {
+        this.context = context;
+        this.variables = variablesIn(lookupElements, false);
+        this.methods = methodsIn(lookupElements);
+    }
+
+    private static List<ExecutableElement> methodsIn(List<? extends Element> lookupElements) {
+        List<ExecutableElement> methods = new ArrayList<>();
+        for (Element variable : lookupElements) {
+            ElementKind kind = variable.getKind();
+            if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) {
+                methods.add((ExecutableElement) variable);
+            }
+        }
+        return methods;
+    }
+
+    private static List<VariableElement> variablesIn(List<? extends Element> lookupElements, boolean publicOnly) {
+        List<VariableElement> variables = new ArrayList<>();
+        for (Element variable : lookupElements) {
+            ElementKind kind = variable.getKind();
+            if (kind == ElementKind.LOCAL_VARIABLE || kind == ElementKind.PARAMETER || kind == ElementKind.FIELD || kind == ElementKind.ENUM_CONSTANT) {
+                VariableElement variableElement = (VariableElement) variable;
+                if (!publicOnly || variableElement.getModifiers().contains(Modifier.PUBLIC)) {
+                    variables.add(variableElement);
+                }
+            }
+        }
+        return variables;
+    }
+
+    private static String getMethodName(ExecutableElement method) {
+        if (method.getKind() == ElementKind.CONSTRUCTOR) {
+            return CONSTRUCTOR_KEYWORD;
+        } else {
+            return method.getSimpleName().toString();
+        }
+    }
+
+    public void visitBinary(Binary binary) {
+        String operator = binary.getOperator();
+        TypeMirror leftType = binary.getLeft().getResolvedType();
+        TypeMirror rightType = binary.getRight().getResolvedType();
+        if (!ElementUtils.typeEquals(leftType, rightType)) {
+            throw new InvalidExpressionException(String.format("Incompatible operand types %s and %s.", ElementUtils.getSimpleName(leftType), ElementUtils.getSimpleName(rightType)));
+        }
+
+        TypeMirror booleanType = context.getType(boolean.class);
+        boolean valid;
+        if (LOGIC_OPERATORS.contains(operator)) {
+            valid = ElementUtils.typeEquals(leftType, booleanType);
+        } else if (COMPARABLE_OPERATORS.contains(operator)) {
+            valid = ElementUtils.isPrimitive(leftType);
+        } else if (IDENTITY_OPERATORS.contains(operator)) {
+            valid = leftType.getKind().isPrimitive() || leftType.getKind() == TypeKind.DECLARED || leftType.getKind() == TypeKind.ARRAY;
+        } else {
+            throw new InvalidExpressionException(String.format("The operator %s is undefined.", operator));
+        }
+        binary.setResolvedType(booleanType);
+
+        if (!valid) {
+            throw new InvalidExpressionException(String.format("The operator %s is undefined for the argument type(s) %s %s.", operator, ElementUtils.getSimpleName(leftType),
+                            ElementUtils.getSimpleName(rightType)));
+        }
+    }
+
+    public void visitNegate(Negate negate) {
+        TypeMirror booleanType = context.getType(boolean.class);
+        TypeMirror resolvedType = negate.getResolvedType();
+        if (!ElementUtils.typeEquals(resolvedType, booleanType)) {
+            throw new InvalidExpressionException(String.format("The operator %s is undefined for the argument type %s.", "!", ElementUtils.getSimpleName(resolvedType)));
+        }
+    }
+
+    public void visitCall(Call call) {
+        List<ExecutableElement> lookupMethods;
+        DSLExpression receiver = call.getReceiver();
+        if (receiver == null) {
+            lookupMethods = this.methods;
+        } else {
+            TypeMirror type = receiver.getResolvedType();
+            if (type.getKind() == TypeKind.DECLARED) {
+                type = context.reloadType(type); // ensure ECJ has the type loaded
+                lookupMethods = ElementFilter.methodsIn(context.getEnvironment().getElementUtils().getAllMembers((TypeElement) ((DeclaredType) type).asElement()));
+            } else {
+                lookupMethods = Collections.emptyList();
+            }
+        }
+
+        ExecutableElement foundWithName = null;
+        outer: for (ExecutableElement method : lookupMethods) {
+            if (getMethodName(method).equals(call.getName())) {
+                foundWithName = method;
+
+                List<? extends VariableElement> parameters = method.getParameters();
+                if (parameters.size() != call.getParameters().size()) {
+                    continue outer;
+                }
+
+                int parameterIndex = 0;
+                for (DSLExpression expression : call.getParameters()) {
+                    TypeMirror sourceType = expression.getResolvedType();
+                    TypeMirror targetType = parameters.get(parameterIndex).asType();
+                    if (!ElementUtils.isAssignable(sourceType, targetType)) {
+                        continue outer;
+                    }
+                    parameterIndex++;
+                }
+                call.setResolvedMethod(method);
+                break;
+            }
+        }
+        if (call.getResolvedMethod() == null) {
+            if (foundWithName == null) {
+                // parameter mismatch
+                throw new InvalidExpressionException(String.format("The method %s is undefined for the enclosing scope.", call.getName()));
+            } else {
+                StringBuilder arguments = new StringBuilder();
+                String sep = "";
+                for (DSLExpression expression : call.getParameters()) {
+                    arguments.append(sep).append(ElementUtils.getSimpleName(expression.getResolvedType()));
+                    sep = ", ";
+                }
+                // name mismatch
+                throw new InvalidExpressionException(String.format("The method %s in the type %s is not applicable for the arguments %s.", //
+                                ElementUtils.getReadableSignature(foundWithName), //
+                                ElementUtils.getSimpleName((TypeElement) foundWithName.getEnclosingElement()), arguments.toString()));
+            }
+        }
+    }
+
+    public void visitVariable(Variable variable) {
+        List<VariableElement> lookupVariables;
+        DSLExpression receiver = variable.getReceiver();
+        if (receiver == null) {
+            lookupVariables = this.variables;
+        } else {
+            TypeMirror type = receiver.getResolvedType();
+            if (type.getKind() == TypeKind.DECLARED) {
+                type = context.reloadType(type); // ensure ECJ has the type loaded
+                lookupVariables = variablesIn(context.getEnvironment().getElementUtils().getAllMembers((TypeElement) ((DeclaredType) type).asElement()), true);
+            } else if (type.getKind() == TypeKind.ARRAY) {
+                lookupVariables = Arrays.<VariableElement> asList(new CodeVariableElement(context.getType(int.class), "length"));
+            } else {
+                lookupVariables = Collections.emptyList();
+            }
+        }
+
+        for (VariableElement variableElement : lookupVariables) {
+            if (variableElement.getSimpleName().toString().equals(variable.getName())) {
+                variable.setResolvedVariable(variableElement);
+                break;
+            }
+        }
+        if (variable.getResolvedVariable() == null) {
+            throw new InvalidExpressionException(String.format("%s cannot be resolved.", variable.getName()));
+        }
+    }
+
+    public void visitIntLiteral(IntLiteral binary) {
+        try {
+            binary.setResolvedType(context.getType(int.class));
+            binary.setResolvedValueInt(Integer.parseInt(binary.getLiteral()));
+        } catch (NumberFormatException e) {
+            throw new InvalidExpressionException(String.format("Type mismatch: cannot convert from String '%s' to int", binary.getLiteral()));
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Expression.atg	Fri Jan 23 02:55:23 2015 +0100
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This is the grammar for DSL expressions that is used to automatically generate the Parser.java and Scanner.java
+ * files. You can download the parser generator Coco/R from http://ssw.jku.at/coco/. Then run
+ * "java -jar Coco.jar Expression.atg"
+ */
+
+COMPILER Expression
+
+CHARACTERS
+
+letter = 'A'..'Z' + 'a'..'z'.
+nonZeroDigit = "123456789".
+digit = "0123456789".
+
+TOKENS
+
+identifier = letter {letter | digit}.
+numericLiteral = "0" | nonZeroDigit { digit }.
+
+PRAGMAS
+
+PRODUCTIONS
+
+
+Expression<out DSLExpression result>
+=
+NegateFactor<out result>
+.
+
+NegateFactor<out DSLExpression  result>
+=                                               (. boolean negated = false; .)
+[
+    "!"                                         (. negated = true; .)
+]                                        
+    LogicFactor<out result>                     (. result = negated ? new Negate(result) : result;.)
+.
+
+
+LogicFactor<out DSLExpression  result>
+=
+Factor<out result>
+[
+    ("<" | "<=" | ">" | ">=" | "==" | "!=" )    (. Token op = t; .)
+    Factor<out DSLExpression  right>            (.  result = new Binary(op.val, result, right); .)
+]
+.
+
+
+Factor<out DSLExpression result>
+=                                               (. result = null; .)
+
+(
+    MemberExpression<out result, result>
+|
+    numericLiteral                              (. result = new IntLiteral(t.val); .)
+|
+    "("                                        
+    Expression<out result>                      
+    ")"                                        
+                                                
+)
+.
+
+MemberExpression<out DSLExpression result, DSLExpression receiver>
+=                                               (. result = null; .)
+(
+    
+    identifier                                  (. Variable variable = new Variable(receiver, t.val); .)
+                                                (. result = variable; .)
+[
+
+    "("                                         (. List<DSLExpression> parameters = new ArrayList<>();
+                                                   DSLExpression parameter; .)
+    [
+        Expression<out parameter>               (. parameters.add(parameter); .)
+        {
+            ","
+            Expression<out parameter>           (. parameters.add(parameter); .)
+        }
+    ]
+    ")"                                         (. result = new Call(variable.getReceiver(), variable.getName(), parameters); .)
+]
+                                                
+)
+[
+   "." MemberExpression<out result, result>
+]
+.
+END Expression.
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/InvalidExpressionException.java	Fri Jan 23 02:55:23 2015 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.expression;
+
+public class InvalidExpressionException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    public InvalidExpressionException(String message) {
+        super(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.frame	Fri Jan 23 02:55:23 2015 +0100
@@ -0,0 +1,211 @@
+/*-------------------------------------------------------------------------
+Compiler Generator Coco/R,
+Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
+extended by M. Loeberbauer & A. Woess, Univ. of Linz
+ported from C# to Java by Wolfgang Ahorner
+with improvements by Pat Terry, Rhodes University
+
+This program is free software; you can redistribute it and/or modify it 
+under the terms of the GNU General Public License as published by the 
+Free Software Foundation; either version 2, or (at your option) any 
+later version.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
+for more details.
+
+You should have received a copy of the GNU General Public License along 
+with this program; if not, write to the Free Software Foundation, Inc., 
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+As an exception, it is allowed to write an extension of Coco/R that is
+used as a plugin in non-free software.
+
+If not otherwise stated, any source code generated by Coco/R (other than 
+Coco/R itself) does not fall under the GNU General Public License.
+------------------------------------------------------------------------*/
+-->begin
+package com.oracle.truffle.dsl.processor.expression;
+
+import java.util.*;
+import java.io.*;
+import java.nio.charset.*;
+
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.*;
+
+// Checkstyle: stop
+// @formatter:off
+class Parser {
+-->constants
+    static final boolean _T = true;
+    static final boolean _x = false;
+    static final int minErrDist = 2;
+
+    public Token t; // last recognized token
+    public Token la; // lookahead token
+    int errDist = minErrDist;
+
+    public final Scanner scanner;
+    public final Errors errors;
+    
+    -->declarations
+    public Parser(InputStream input) {
+        this.scanner = new Scanner(input);
+        errors = new Errors();
+    }
+
+    void SynErr(int n) {
+        if (errDist >= minErrDist)
+            errors.SynErr(la.line, la.col, n);
+        errDist = 0;
+    }
+
+    public void SemErr(String msg) {
+        if (errDist >= minErrDist)
+            errors.SemErr(t.line, t.col, msg);
+        errDist = 0;
+    }
+
+    void Get() {
+        for (;;) {
+            t = la;
+            la = scanner.Scan();
+            if (la.kind <= maxT) {
+                ++errDist;
+                break;
+            }
+-->pragmas
+            la = t;
+        }
+    }
+
+    void Expect(int n) {
+        if (la.kind == n)
+            Get();
+        else {
+            SynErr(n);
+        }
+    }
+
+    boolean StartOf(int s) {
+        return set[s][la.kind];
+    }
+
+    void ExpectWeak(int n, int follow) {
+        if (la.kind == n)
+            Get();
+        else {
+            SynErr(n);
+            while (!StartOf(follow))
+                Get();
+        }
+    }
+
+    boolean WeakSeparator(int n, int syFol, int repFol) {
+        int kind = la.kind;
+        if (kind == n) {
+            Get();
+            return true;
+        } else if (StartOf(repFol))
+            return false;
+        else {
+            SynErr(n);
+            while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) {
+                Get();
+                kind = la.kind;
+            }
+            return StartOf(syFol);
+        }
+    }
+
+-->productions
+
+    private DSLExpression parseImpl() {
+        la = new Token();
+        la.val = "";
+        Get();
+        DSLExpression result = -->parseRoot
+        return result;
+    }
+
+    private static final boolean[][] set = {
+-->initialization
+    };
+
+    public static DSLExpression parse(InputStream input) {
+        Parser parser = new Parser(input);
+        DSLExpression result = parser.parseImpl();
+        if (parser.errors.errors.size() > 0) {
+            StringBuilder msg = new StringBuilder();
+            for (String error : parser.errors.errors) {
+                msg.append(error).append("\n");
+            }
+            throw new InvalidExpressionException(msg.toString());
+        }
+        return result;
+    }
+
+    public static DSLExpression parse(String s) {
+        return parse(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8)));
+    }
+} // end Parser
+
+class Errors {
+
+    protected final List<String> errors = new ArrayList<>();
+    public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
+
+    protected void printMsg(int line, int column, String msg) {
+        StringBuffer b = new StringBuffer(errMsgFormat);
+        int pos = b.indexOf("{0}");
+        if (pos >= 0) {
+            b.delete(pos, pos + 3);
+            b.insert(pos, line);
+        }
+        pos = b.indexOf("{1}");
+        if (pos >= 0) {
+            b.delete(pos, pos + 3);
+            b.insert(pos, column);
+        }
+        pos = b.indexOf("{2}");
+        if (pos >= 0)
+            b.replace(pos, pos + 3, msg);
+        errors.add(b.toString());
+    }
+
+    public void SynErr(int line, int col, int n) {
+        String s;
+        switch (n) {-->errors
+            default:
+                s = "error " + n;
+                break;
+        }
+        printMsg(line, col, s);
+    }
+
+    public void SemErr(int line, int col, String s) {
+        printMsg(line, col, s);
+    }
+
+    public void SemErr(String s) {
+        errors.add(s);
+    }
+
+    public void Warning(int line, int col, String s) {
+        printMsg(line, col, s);
+    }
+
+    public void Warning(String s) {
+        errors.add(s);
+    }
+} // Errors
+
+class FatalError extends RuntimeException {
+
+    public static final long serialVersionUID = 1L;
+
+    public FatalError(String s) {
+        super(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.java	Fri Jan 23 02:55:23 2015 +0100
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// The content of this file is automatically generated. DO NOT EDIT.
+
+package com.oracle.truffle.dsl.processor.expression;
+
+import java.util.*;
+import java.io.*;
+import java.nio.charset.*;
+
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.*;
+
+// Checkstyle: stop
+// @formatter:off
+class Parser {
+	public static final int _EOF = 0;
+	public static final int _identifier = 1;
+	public static final int _numericLiteral = 2;
+	public static final int maxT = 14;
+
+    static final boolean _T = true;
+    static final boolean _x = false;
+    static final int minErrDist = 2;
+
+    public Token t; // last recognized token
+    public Token la; // lookahead token
+    int errDist = minErrDist;
+
+    public final Scanner scanner;
+    public final Errors errors;
+    
+    
+    public Parser(InputStream input) {
+        this.scanner = new Scanner(input);
+        errors = new Errors();
+    }
+
+    void SynErr(int n) {
+        if (errDist >= minErrDist)
+            errors.SynErr(la.line, la.col, n);
+        errDist = 0;
+    }
+
+    public void SemErr(String msg) {
+        if (errDist >= minErrDist)
+            errors.SemErr(t.line, t.col, msg);
+        errDist = 0;
+    }
+
+    void Get() {
+        for (;;) {
+            t = la;
+            la = scanner.Scan();
+            if (la.kind <= maxT) {
+                ++errDist;
+                break;
+            }
+
+            la = t;
+        }
+    }
+
+    void Expect(int n) {
+        if (la.kind == n)
+            Get();
+        else {
+            SynErr(n);
+        }
+    }
+
+    boolean StartOf(int s) {
+        return set[s][la.kind];
+    }
+
+    void ExpectWeak(int n, int follow) {
+        if (la.kind == n)
+            Get();
+        else {
+            SynErr(n);
+            while (!StartOf(follow))
+                Get();
+        }
+    }
+
+    boolean WeakSeparator(int n, int syFol, int repFol) {
+        int kind = la.kind;
+        if (kind == n) {
+            Get();
+            return true;
+        } else if (StartOf(repFol))
+            return false;
+        else {
+            SynErr(n);
+            while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) {
+                Get();
+                kind = la.kind;
+            }
+            return StartOf(syFol);
+        }
+    }
+
+	DSLExpression  Expression() {
+		DSLExpression  result;
+		result = NegateFactor();
+		return result;
+	}
+
+	DSLExpression   NegateFactor() {
+		DSLExpression   result;
+		boolean negated = false; 
+		if (la.kind == 3) {
+			Get();
+			negated = true; 
+		}
+		result = LogicFactor();
+		result = negated ? new Negate(result) : result;
+		return result;
+	}
+
+	DSLExpression   LogicFactor() {
+		DSLExpression   result;
+		result = Factor();
+		if (StartOf(1)) {
+			switch (la.kind) {
+			case 4: {
+				Get();
+				break;
+			}
+			case 5: {
+				Get();
+				break;
+			}
+			case 6: {
+				Get();
+				break;
+			}
+			case 7: {
+				Get();
+				break;
+			}
+			case 8: {
+				Get();
+				break;
+			}
+			case 9: {
+				Get();
+				break;
+			}
+			}
+			Token op = t; 
+			DSLExpression  right = Factor();
+			result = new Binary(op.val, result, right); 
+		}
+		return result;
+	}
+
+	DSLExpression  Factor() {
+		DSLExpression  result;
+		result = null; 
+		if (la.kind == 1) {
+			result = MemberExpression(result);
+		} else if (la.kind == 2) {
+			Get();
+			result = new IntLiteral(t.val); 
+		} else if (la.kind == 10) {
+			Get();
+			result = Expression();
+			Expect(11);
+		} else SynErr(15);
+		return result;
+	}
+
+	DSLExpression  MemberExpression(DSLExpression receiver) {
+		DSLExpression  result;
+		result = null; 
+		Expect(1);
+		Variable variable = new Variable(receiver, t.val); 
+		result = variable; 
+		if (la.kind == 10) {
+			Get();
+			List<DSLExpression> parameters = new ArrayList<>();
+			DSLExpression parameter; 
+			if (StartOf(2)) {
+				parameter = Expression();
+				parameters.add(parameter); 
+				while (la.kind == 12) {
+					Get();
+					parameter = Expression();
+					parameters.add(parameter); 
+				}
+			}
+			Expect(11);
+			result = new Call(variable.getReceiver(), variable.getName(), parameters); 
+		}
+		if (la.kind == 13) {
+			Get();
+			result = MemberExpression(result);
+		}
+		return result;
+	}
+
+
+
+    private DSLExpression parseImpl() {
+        la = new Token();
+        la.val = "";
+        Get();
+        DSLExpression result = 		Expression();
+		Expect(0);
+
+        return result;
+    }
+
+    private static final boolean[][] set = {
+		{_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x},
+		{_x,_x,_x,_x, _T,_T,_T,_T, _T,_T,_x,_x, _x,_x,_x,_x},
+		{_x,_T,_T,_T, _x,_x,_x,_x, _x,_x,_T,_x, _x,_x,_x,_x}
+
+    };
+
+    public static DSLExpression parse(InputStream input) {
+        Parser parser = new Parser(input);
+        DSLExpression result = parser.parseImpl();
+        if (parser.errors.errors.size() > 0) {
+            StringBuilder msg = new StringBuilder();
+            for (String error : parser.errors.errors) {
+                msg.append(error).append("\n");
+            }
+            throw new InvalidExpressionException(msg.toString());
+        }
+        return result;
+    }
+
+    public static DSLExpression parse(String s) {
+        return parse(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8)));
+    }
+} // end Parser
+
+class Errors {
+
+    protected final List<String> errors = new ArrayList<>();
+    public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
+
+    protected void printMsg(int line, int column, String msg) {
+        StringBuffer b = new StringBuffer(errMsgFormat);
+        int pos = b.indexOf("{0}");
+        if (pos >= 0) {
+            b.delete(pos, pos + 3);
+            b.insert(pos, line);
+        }
+        pos = b.indexOf("{1}");
+        if (pos >= 0) {
+            b.delete(pos, pos + 3);
+            b.insert(pos, column);
+        }
+        pos = b.indexOf("{2}");
+        if (pos >= 0)
+            b.replace(pos, pos + 3, msg);
+        errors.add(b.toString());
+    }
+
+    public void SynErr(int line, int col, int n) {
+        String s;
+        switch (n) {
+			case 0: s = "EOF expected"; break;
+			case 1: s = "identifier expected"; break;
+			case 2: s = "numericLiteral expected"; break;
+			case 3: s = "\"!\" expected"; break;
+			case 4: s = "\"<\" expected"; break;
+			case 5: s = "\"<=\" expected"; break;
+			case 6: s = "\">\" expected"; break;
+			case 7: s = "\">=\" expected"; break;
+			case 8: s = "\"==\" expected"; break;
+			case 9: s = "\"!=\" expected"; break;
+			case 10: s = "\"(\" expected"; break;
+			case 11: s = "\")\" expected"; break;
+			case 12: s = "\",\" expected"; break;
+			case 13: s = "\".\" expected"; break;
+			case 14: s = "??? expected"; break;
+			case 15: s = "invalid Factor"; break;
+            default:
+                s = "error " + n;
+                break;
+        }
+        printMsg(line, col, s);
+    }
+
+    public void SemErr(int line, int col, String s) {
+        printMsg(line, col, s);
+    }
+
+    public void SemErr(String s) {
+        errors.add(s);
+    }
+
+    public void Warning(int line, int col, String s) {
+        printMsg(line, col, s);
+    }
+
+    public void Warning(String s) {
+        errors.add(s);
+    }
+} // Errors
+
+class FatalError extends RuntimeException {
+
+    public static final long serialVersionUID = 1L;
+
+    public FatalError(String s) {
+        super(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.frame	Fri Jan 23 02:55:23 2015 +0100
@@ -0,0 +1,495 @@
+/*-------------------------------------------------------------------------
+Compiler Generator Coco/R,
+Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
+extended by M. Loeberbauer & A. Woess, Univ. of Linz
+ported from C# to Java by Wolfgang Ahorner
+with improvements by Pat Terry, Rhodes University
+
+This program is free software; you can redistribute it and/or modify it 
+under the terms of the GNU General Public License as published by the 
+Free Software Foundation; either version 2, or (at your option) any 
+later version.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
+for more details.
+
+You should have received a copy of the GNU General Public License along 
+with this program; if not, write to the Free Software Foundation, Inc., 
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+As an exception, it is allowed to write an extension of Coco/R that is
+used as a plugin in non-free software.
+
+If not otherwise stated, any source code generated by Coco/R (other than 
+Coco/R itself) does not fall under the GNU General Public License.
+------------------------------------------------------------------------*/
+-->begin
+package com.oracle.truffle.dsl.processor.expression;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.Map;
+import java.util.HashMap;
+
+// Checkstyle: stop
+// @formatter:off
+class Token {
+
+    public int kind; // token kind
+    public int pos; // token position in bytes in the source text (starting at 0)
+    public int charPos; // token position in characters in the source text (starting at 0)
+    public int col; // token column (starting at 1)
+    public int line; // token line (starting at 1)
+    public String val; // token value
+    public Token next; // ML 2005-03-11 Peek tokens are kept in linked list
+}
+
+// -----------------------------------------------------------------------------------
+// Buffer
+// -----------------------------------------------------------------------------------
+class Buffer {
+
+    // This Buffer supports the following cases:
+    // 1) seekable stream (file)
+    // a) whole stream in buffer
+    // b) part of stream in buffer
+    // 2) non seekable stream (network, console)
+
+    public static final int EOF = Character.MAX_VALUE + 1;
+    private static final int MIN_BUFFER_LENGTH = 1024; // 1KB
+    private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
+    private byte[] buf; // input buffer
+    private int bufStart; // position of first byte in buffer relative to input stream
+    private int bufLen; // length of buffer
+    private int fileLen; // length of input stream (may change if stream is no file)
+    private int bufPos; // current position in buffer
+    private RandomAccessFile file; // input stream (seekable)
+    private InputStream stream; // growing input stream (e.g.: console, network)
+
+    public Buffer(InputStream s) {
+        stream = s;
+        fileLen = bufLen = bufStart = bufPos = 0;
+        buf = new byte[MIN_BUFFER_LENGTH];
+    }
+
+    public Buffer(String fileName) {
+        try {
+            file = new RandomAccessFile(fileName, "r");
+            fileLen = (int) file.length();
+            bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH);
+            buf = new byte[bufLen];
+            bufStart = Integer.MAX_VALUE; // nothing in buffer so far
+            if (fileLen > 0)
+                setPos(0); // setup buffer to position 0 (start)
+            else
+                bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid
+            if (bufLen == fileLen)
+                Close();
+        } catch (IOException e) {
+            throw new FatalError("Could not open file " + fileName);
+        }
+    }
+
+    // don't use b after this call anymore
+    // called in UTF8Buffer constructor
+    protected Buffer(Buffer b) {
+        buf = b.buf;
+        bufStart = b.bufStart;
+        bufLen = b.bufLen;
+        fileLen = b.fileLen;
+        bufPos = b.bufPos;
+        file = b.file;
+        stream = b.stream;
+        // keep finalize from closing the file
+        b.file = null;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        super.finalize();
+        Close();
+    }
+
+    protected void Close() {
+        if (file != null) {
+            try {
+                file.close();
+                file = null;
+            } catch (IOException e) {
+                throw new FatalError(e.getMessage());
+            }
+        }
+    }
+
+    public int Read() {
+        if (bufPos < bufLen) {
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else if (getPos() < fileLen) {
+            setPos(getPos()); // shift buffer start to pos
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else if (stream != null && ReadNextStreamChunk() > 0) {
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else {
+            return EOF;
+        }
+    }
+
+    public int Peek() {
+        int curPos = getPos();
+        int ch = Read();
+        setPos(curPos);
+        return ch;
+    }
+
+    // beg .. begin, zero-based, inclusive, in byte
+    // end .. end, zero-based, exclusive, in byte
+    public String GetString(int beg, int end) {
+        int len = 0;
+        char[] buffer = new char[end - beg];
+        int oldPos = getPos();
+        setPos(beg);
+        while (getPos() < end)
+            buffer[len++] = (char) Read();
+        setPos(oldPos);
+        return new String(buffer, 0, len);
+    }
+
+    public int getPos() {
+        return bufPos + bufStart;
+    }
+
+    public void setPos(int value) {
+        if (value >= fileLen && stream != null) {
+            // Wanted position is after buffer and the stream
+            // is not seek-able e.g. network or console,
+            // thus we have to read the stream manually till
+            // the wanted position is in sight.
+            while (value >= fileLen && ReadNextStreamChunk() > 0) {
+                // nothing to do...
+            }
+        }
+
+        if (value < 0 || value > fileLen) {
+            throw new FatalError("buffer out of bounds access, position: " + value);
+        }
+
+        if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
+            bufPos = value - bufStart;
+        } else if (file != null) { // must be swapped in
+            try {
+                file.seek(value);
+                bufLen = file.read(buf);
+                bufStart = value;
+                bufPos = 0;
+            } catch (IOException e) {
+                throw new FatalError(e.getMessage());
+            }
+        } else {
+            // set the position to the end of the file, Pos will return fileLen.
+            bufPos = fileLen - bufStart;
+        }
+    }
+
+    // Read the next chunk of bytes from the stream, increases the buffer
+    // if needed and updates the fields fileLen and bufLen.
+    // Returns the number of bytes read.
+    private int ReadNextStreamChunk() {
+        int free = buf.length - bufLen;
+        if (free == 0) {
+            // in the case of a growing input stream
+            // we can neither seek in the stream, nor can we
+            // foresee the maximum length, thus we must adapt
+            // the buffer size on demand.
+            byte[] newBuf = new byte[bufLen * 2];
+            System.arraycopy(buf, 0, newBuf, 0, bufLen);
+            buf = newBuf;
+            free = bufLen;
+        }
+
+        int read;
+        try {
+            read = stream.read(buf, bufLen, free);
+        } catch (IOException ioex) {
+            throw new FatalError(ioex.getMessage());
+        }
+
+        if (read > 0) {
+            fileLen = bufLen = (bufLen + read);
+            return read;
+        }
+        // end of stream reached
+        return 0;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// UTF8Buffer
+// -----------------------------------------------------------------------------------
+class UTF8Buffer extends Buffer {
+
+    UTF8Buffer(Buffer b) {
+        super(b);
+    }
+
+    @Override
+    public int Read() {
+        int ch;
+        do {
+            ch = super.Read();
+            // until we find a utf8 start (0xxxxxxx or 11xxxxxx)
+        } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
+        if (ch < 128 || ch == EOF) {
+            // nothing to do, first 127 chars are the same in ascii and utf8
+            // 0xxxxxxx or end of file character
+        } else if ((ch & 0xF0) == 0xF0) {
+            // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+            int c1 = ch & 0x07;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = super.Read();
+            int c3 = ch & 0x3F;
+            ch = super.Read();
+            int c4 = ch & 0x3F;
+            ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
+        } else if ((ch & 0xE0) == 0xE0) {
+            // 1110xxxx 10xxxxxx 10xxxxxx
+            int c1 = ch & 0x0F;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = super.Read();
+            int c3 = ch & 0x3F;
+            ch = (((c1 << 6) | c2) << 6) | c3;
+        } else if ((ch & 0xC0) == 0xC0) {
+            // 110xxxxx 10xxxxxx
+            int c1 = ch & 0x1F;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = (c1 << 6) | c2;
+        }
+        return ch;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// StartStates -- maps characters to start states of tokens
+// -----------------------------------------------------------------------------------
+class StartStates {
+
+    private static class Elem {
+
+        public int key, val;
+        public Elem next;
+
+        public Elem(int key, int val) {
+            this.key = key;
+            this.val = val;
+        }
+    }
+
+    private Elem[] tab = new Elem[128];
+
+    public void set(int key, int val) {
+        Elem e = new Elem(key, val);
+        int k = key % 128;
+        e.next = tab[k];
+        tab[k] = e;
+    }
+
+    public int state(int key) {
+        Elem e = tab[key % 128];
+        while (e != null && e.key != key)
+            e = e.next;
+        return e == null ? 0 : e.val;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// Scanner
+// -----------------------------------------------------------------------------------
+@SuppressWarnings({"rawtypes"})
+public class Scanner {
+
+    static final char EOL = '\n';
+    static final int eofSym = 0;
+-->declarations
+
+    public Buffer buffer; // scanner buffer
+
+    Token t; // current token
+    int ch; // current input character
+    int pos; // byte position of current character
+    int charPos; // position by unicode characters starting with 0
+    int col; // column number of current character
+    int line; // line number of current character
+    int oldEols; // EOLs that appeared in a comment;
+    static final StartStates start; // maps initial token character to start state
+    static final Map literals; // maps literal strings to literal kinds
+
+    Token tokens; // list of tokens already peeked (first token is a dummy)
+    Token pt; // current peek token
+
+    char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged
+    int tlen; // length of current token
+
+    static {
+        start = new StartStates();
+        literals = new HashMap();
+-->initialization
+    }
+
+    public Scanner(String fileName) {
+        buffer = new Buffer(fileName);
+        Init();
+    }
+
+    public Scanner(InputStream s) {
+        buffer = new Buffer(s);
+        Init();
+    }
+
+    void Init() {
+        pos = -1;
+        line = 1;
+        col = 0;
+        charPos = -1;
+        oldEols = 0;
+        NextCh();
+        if (ch == 0xEF) { // check optional byte order mark for UTF-8
+            NextCh();
+            int ch1 = ch;
+            NextCh();
+            int ch2 = ch;
+            if (ch1 != 0xBB || ch2 != 0xBF) {
+                throw new FatalError("Illegal byte order mark at start of file");
+            }
+            buffer = new UTF8Buffer(buffer);
+            col = 0;
+            charPos = -1;
+            NextCh();
+        }
+        pt = tokens = new Token(); // first token is a dummy
+    }
+
+    void NextCh() {
+        if (oldEols > 0) {
+            ch = EOL;
+            oldEols--;
+        } else {
+            pos = buffer.getPos();
+            // buffer reads unicode chars, if UTF8 has been detected
+            ch = buffer.Read();
+            col++;
+            charPos++;
+            // replace isolated '\r' by '\n' in order to make
+            // eol handling uniform across Windows, Unix and Mac
+            if (ch == '\r' && buffer.Peek() != '\n')
+                ch = EOL;
+            if (ch == EOL) {
+                line++;
+                col = 0;
+            }
+        }
+-->casing
+    }
+
+    void AddCh() {
+        if (tlen >= tval.length) {
+            char[] newBuf = new char[2 * tval.length];
+            System.arraycopy(tval, 0, newBuf, 0, tval.length);
+            tval = newBuf;
+        }
+        if (ch != Buffer.EOF) {
+-->casing2
+            NextCh();
+        }
+    }
+
+-->comments
+
+    void CheckLiteral() {
+        String val = t.val;
+-->casing3
+        Object kind = literals.get(val);
+        if (kind != null) {
+            t.kind = ((Integer) kind).intValue();
+        }
+    }
+
+    Token NextToken() {
+        while (ch == ' ' || 
+-->scan1
+        ) NextCh();
+-->scan2
+        int recKind = noSym;
+        int recEnd = pos;
+        t = new Token();
+        t.pos = pos;
+        t.col = col;
+        t.line = line;
+        t.charPos = charPos;
+        int state = start.state(ch);
+        tlen = 0;
+        AddCh();
+
+        loop: for (;;) {
+            switch (state) {
+                case -1: {
+                    t.kind = eofSym;
+                    break loop;
+                } // NextCh already done
+                case 0: {
+                    if (recKind != noSym) {
+                        tlen = recEnd - t.pos;
+                        SetScannerBehindT();
+                    }
+                    t.kind = recKind;
+                    break loop;
+                } // NextCh already done
+-->scan3
+            }
+        }
+        t.val = new String(tval, 0, tlen);
+        return t;
+    }
+
+    private void SetScannerBehindT() {
+        buffer.setPos(t.pos);
+        NextCh();
+        line = t.line;
+        col = t.col;
+        charPos = t.charPos;
+        for (int i = 0; i < tlen; i++)
+            NextCh();
+    }
+
+    // get the next token (possibly a token already seen during peeking)
+    public Token Scan() {
+        if (tokens.next == null) {
+            return NextToken();
+        } else {
+            pt = tokens = tokens.next;
+            return tokens;
+        }
+    }
+
+    // get the next token, ignore pragmas
+    public Token Peek() {
+        do {
+            if (pt.next == null) {
+                pt.next = NextToken();
+            }
+            pt = pt.next;
+        } while (pt.kind > maxT); // skip pragmas
+
+        return pt;
+    }
+
+    // make sure that peeking starts at current scan position
+    public void ResetPeek() {
+        pt = tokens;
+    }
+
+} // end Scanner
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.java	Fri Jan 23 02:55:23 2015 +0100
@@ -0,0 +1,549 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// The content of this file is automatically generated. DO NOT EDIT.
+
+package com.oracle.truffle.dsl.processor.expression;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.Map;
+import java.util.HashMap;
+
+// Checkstyle: stop
+// @formatter:off
+class Token {
+
+    public int kind; // token kind
+    public int pos; // token position in bytes in the source text (starting at 0)
+    public int charPos; // token position in characters in the source text (starting at 0)
+    public int col; // token column (starting at 1)
+    public int line; // token line (starting at 1)
+    public String val; // token value
+    public Token next; // ML 2005-03-11 Peek tokens are kept in linked list
+}
+
+// -----------------------------------------------------------------------------------
+// Buffer
+// -----------------------------------------------------------------------------------
+class Buffer {
+
+    // This Buffer supports the following cases:
+    // 1) seekable stream (file)
+    // a) whole stream in buffer
+    // b) part of stream in buffer
+    // 2) non seekable stream (network, console)
+
+    public static final int EOF = Character.MAX_VALUE + 1;
+    private static final int MIN_BUFFER_LENGTH = 1024; // 1KB
+    private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
+    private byte[] buf; // input buffer
+    private int bufStart; // position of first byte in buffer relative to input stream
+    private int bufLen; // length of buffer
+    private int fileLen; // length of input stream (may change if stream is no file)
+    private int bufPos; // current position in buffer
+    private RandomAccessFile file; // input stream (seekable)
+    private InputStream stream; // growing input stream (e.g.: console, network)
+
+    public Buffer(InputStream s) {
+        stream = s;
+        fileLen = bufLen = bufStart = bufPos = 0;
+        buf = new byte[MIN_BUFFER_LENGTH];
+    }
+
+    public Buffer(String fileName) {
+        try {
+            file = new RandomAccessFile(fileName, "r");
+            fileLen = (int) file.length();
+            bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH);
+            buf = new byte[bufLen];
+            bufStart = Integer.MAX_VALUE; // nothing in buffer so far
+            if (fileLen > 0)
+                setPos(0); // setup buffer to position 0 (start)
+            else
+                bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid
+            if (bufLen == fileLen)
+                Close();
+        } catch (IOException e) {
+            throw new FatalError("Could not open file " + fileName);
+        }
+    }
+
+    // don't use b after this call anymore
+    // called in UTF8Buffer constructor
+    protected Buffer(Buffer b) {
+        buf = b.buf;
+        bufStart = b.bufStart;
+        bufLen = b.bufLen;
+        fileLen = b.fileLen;
+        bufPos = b.bufPos;
+        file = b.file;
+        stream = b.stream;
+        // keep finalize from closing the file
+        b.file = null;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        super.finalize();
+        Close();
+    }
+
+    protected void Close() {
+        if (file != null) {
+            try {
+                file.close();
+                file = null;
+            } catch (IOException e) {
+                throw new FatalError(e.getMessage());
+            }
+        }
+    }
+
+    public int Read() {
+        if (bufPos < bufLen) {
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else if (getPos() < fileLen) {
+            setPos(getPos()); // shift buffer start to pos
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else if (stream != null && ReadNextStreamChunk() > 0) {
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else {
+            return EOF;
+        }
+    }
+
+    public int Peek() {
+        int curPos = getPos();
+        int ch = Read();
+        setPos(curPos);
+        return ch;
+    }
+
+    // beg .. begin, zero-based, inclusive, in byte
+    // end .. end, zero-based, exclusive, in byte
+    public String GetString(int beg, int end) {
+        int len = 0;
+        char[] buffer = new char[end - beg];
+        int oldPos = getPos();
+        setPos(beg);
+        while (getPos() < end)
+            buffer[len++] = (char) Read();
+        setPos(oldPos);
+        return new String(buffer, 0, len);
+    }
+
+    public int getPos() {
+        return bufPos + bufStart;
+    }
+
+    public void setPos(int value) {
+        if (value >= fileLen && stream != null) {
+            // Wanted position is after buffer and the stream
+            // is not seek-able e.g. network or console,
+            // thus we have to read the stream manually till
+            // the wanted position is in sight.
+            while (value >= fileLen && ReadNextStreamChunk() > 0) {
+                // nothing to do...
+            }
+        }
+
+        if (value < 0 || value > fileLen) {
+            throw new FatalError("buffer out of bounds access, position: " + value);
+        }
+
+        if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
+            bufPos = value - bufStart;
+        } else if (file != null) { // must be swapped in
+            try {
+                file.seek(value);
+                bufLen = file.read(buf);
+                bufStart = value;
+                bufPos = 0;
+            } catch (IOException e) {
+                throw new FatalError(e.getMessage());
+            }
+        } else {
+            // set the position to the end of the file, Pos will return fileLen.
+            bufPos = fileLen - bufStart;
+        }
+    }
+
+    // Read the next chunk of bytes from the stream, increases the buffer
+    // if needed and updates the fields fileLen and bufLen.
+    // Returns the number of bytes read.
+    private int ReadNextStreamChunk() {
+        int free = buf.length - bufLen;
+        if (free == 0) {
+            // in the case of a growing input stream
+            // we can neither seek in the stream, nor can we
+            // foresee the maximum length, thus we must adapt
+            // the buffer size on demand.
+            byte[] newBuf = new byte[bufLen * 2];
+            System.arraycopy(buf, 0, newBuf, 0, bufLen);
+            buf = newBuf;
+            free = bufLen;
+        }
+
+        int read;
+        try {
+            read = stream.read(buf, bufLen, free);
+        } catch (IOException ioex) {
+            throw new FatalError(ioex.getMessage());
+        }
+
+        if (read > 0) {
+            fileLen = bufLen = (bufLen + read);
+            return read;
+        }
+        // end of stream reached
+        return 0;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// UTF8Buffer
+// -----------------------------------------------------------------------------------
+class UTF8Buffer extends Buffer {
+
+    UTF8Buffer(Buffer b) {
+        super(b);
+    }
+
+    @Override
+    public int Read() {
+        int ch;
+        do {
+            ch = super.Read();
+            // until we find a utf8 start (0xxxxxxx or 11xxxxxx)
+        } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
+        if (ch < 128 || ch == EOF) {
+            // nothing to do, first 127 chars are the same in ascii and utf8
+            // 0xxxxxxx or end of file character
+        } else if ((ch & 0xF0) == 0xF0) {
+            // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+            int c1 = ch & 0x07;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = super.Read();
+            int c3 = ch & 0x3F;
+            ch = super.Read();
+            int c4 = ch & 0x3F;
+            ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
+        } else if ((ch & 0xE0) == 0xE0) {
+            // 1110xxxx 10xxxxxx 10xxxxxx
+            int c1 = ch & 0x0F;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = super.Read();
+            int c3 = ch & 0x3F;
+            ch = (((c1 << 6) | c2) << 6) | c3;
+        } else if ((ch & 0xC0) == 0xC0) {
+            // 110xxxxx 10xxxxxx
+            int c1 = ch & 0x1F;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = (c1 << 6) | c2;
+        }
+        return ch;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// StartStates -- maps characters to start states of tokens
+// -----------------------------------------------------------------------------------
+class StartStates {
+
+    private static class Elem {
+
+        public int key, val;
+        public Elem next;
+
+        public Elem(int key, int val) {
+            this.key = key;
+            this.val = val;
+        }
+    }
+
+    private Elem[] tab = new Elem[128];
+
+    public void set(int key, int val) {
+        Elem e = new Elem(key, val);
+        int k = key % 128;
+        e.next = tab[k];
+        tab[k] = e;
+    }
+
+    public int state(int key) {
+        Elem e = tab[key % 128];
+        while (e != null && e.key != key)
+            e = e.next;
+        return e == null ? 0 : e.val;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// Scanner
+// -----------------------------------------------------------------------------------
+@SuppressWarnings({"rawtypes"})
+public class Scanner {
+
+    static final char EOL = '\n';
+    static final int eofSym = 0;
+	static final int maxT = 14;
+	static final int noSym = 14;
+
+
+    public Buffer buffer; // scanner buffer
+
+    Token t; // current token
+    int ch; // current input character
+    int pos; // byte position of current character
+    int charPos; // position by unicode characters starting with 0
+    int col; // column number of current character
+    int line; // line number of current character
+    int oldEols; // EOLs that appeared in a comment;
+    static final StartStates start; // maps initial token character to start state
+    static final Map literals; // maps literal strings to literal kinds
+
+    Token tokens; // list of tokens already peeked (first token is a dummy)
+    Token pt; // current peek token
+
+    char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged
+    int tlen; // length of current token
+
+    static {
+        start = new StartStates();
+        literals = new HashMap();
+		for (int i = 65; i <= 90; ++i) start.set(i, 1);
+		for (int i = 97; i <= 122; ++i) start.set(i, 1);
+		for (int i = 49; i <= 57; ++i) start.set(i, 2);
+		start.set(48, 3); 
+		start.set(33, 13); 
+		start.set(60, 14); 
+		start.set(62, 15); 
+		start.set(61, 6); 
+		start.set(40, 9); 
+		start.set(41, 10); 
+		start.set(44, 11); 
+		start.set(46, 12); 
+		start.set(Buffer.EOF, -1);
+
+    }
+
+    public Scanner(String fileName) {
+        buffer = new Buffer(fileName);
+        Init();
+    }
+
+    public Scanner(InputStream s) {
+        buffer = new Buffer(s);
+        Init();
+    }
+
+    void Init() {
+        pos = -1;
+        line = 1;
+        col = 0;
+        charPos = -1;
+        oldEols = 0;
+        NextCh();
+        if (ch == 0xEF) { // check optional byte order mark for UTF-8
+            NextCh();
+            int ch1 = ch;
+            NextCh();
+            int ch2 = ch;
+            if (ch1 != 0xBB || ch2 != 0xBF) {
+                throw new FatalError("Illegal byte order mark at start of file");
+            }
+            buffer = new UTF8Buffer(buffer);
+            col = 0;
+            charPos = -1;
+            NextCh();
+        }
+        pt = tokens = new Token(); // first token is a dummy
+    }
+
+    void NextCh() {
+        if (oldEols > 0) {
+            ch = EOL;
+            oldEols--;
+        } else {
+            pos = buffer.getPos();
+            // buffer reads unicode chars, if UTF8 has been detected
+            ch = buffer.Read();
+            col++;
+            charPos++;
+            // replace isolated '\r' by '\n' in order to make
+            // eol handling uniform across Windows, Unix and Mac
+            if (ch == '\r' && buffer.Peek() != '\n')
+                ch = EOL;
+            if (ch == EOL) {
+                line++;
+                col = 0;
+            }
+        }
+
+    }
+
+    void AddCh() {
+        if (tlen >= tval.length) {
+            char[] newBuf = new char[2 * tval.length];
+            System.arraycopy(tval, 0, newBuf, 0, tval.length);
+            tval = newBuf;
+        }
+        if (ch != Buffer.EOF) {
+			tval[tlen++] = (char)ch; 
+
+            NextCh();
+        }
+    }
+
+
+
+    void CheckLiteral() {
+        String val = t.val;
+
+        Object kind = literals.get(val);
+        if (kind != null) {
+            t.kind = ((Integer) kind).intValue();
+        }
+    }
+
+    Token NextToken() {
+        while (ch == ' ' || 
+			false
+        ) NextCh();
+
+        int recKind = noSym;
+        int recEnd = pos;
+        t = new Token();
+        t.pos = pos;
+        t.col = col;
+        t.line = line;
+        t.charPos = charPos;
+        int state = start.state(ch);
+        tlen = 0;
+        AddCh();
+
+        loop: for (;;) {
+            switch (state) {
+                case -1: {
+                    t.kind = eofSym;
+                    break loop;
+                } // NextCh already done
+                case 0: {
+                    if (recKind != noSym) {
+                        tlen = recEnd - t.pos;
+                        SetScannerBehindT();
+                    }
+                    t.kind = recKind;
+                    break loop;
+                } // NextCh already done
+				case 1:
+					recEnd = pos; recKind = 1;
+					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
+					else {t.kind = 1; break loop;}
+				case 2:
+					recEnd = pos; recKind = 2;
+					if (ch >= '0' && ch <= '9') {AddCh(); state = 2; break;}
+					else {t.kind = 2; break loop;}
+				case 3:
+					{t.kind = 2; break loop;}
+				case 4:
+					{t.kind = 5; break loop;}
+				case 5:
+					{t.kind = 7; break loop;}
+				case 6:
+					if (ch == '=') {AddCh(); state = 7; break;}
+					else {state = 0; break;}
+				case 7:
+					{t.kind = 8; break loop;}
+				case 8:
+					{t.kind = 9; break loop;}
+				case 9:
+					{t.kind = 10; break loop;}
+				case 10:
+					{t.kind = 11; break loop;}
+				case 11:
+					{t.kind = 12; break loop;}
+				case 12:
+					{t.kind = 13; break loop;}
+				case 13:
+					recEnd = pos; recKind = 3;
+					if (ch == '=') {AddCh(); state = 8; break;}
+					else {t.kind = 3; break loop;}
+				case 14:
+					recEnd = pos; recKind = 4;
+					if (ch == '=') {AddCh(); state = 4; break;}
+					else {t.kind = 4; break loop;}
+				case 15:
+					recEnd = pos; recKind = 6;
+					if (ch == '=') {AddCh(); state = 5; break;}
+					else {t.kind = 6; break loop;}
+
+            }
+        }
+        t.val = new String(tval, 0, tlen);
+        return t;
+    }
+
+    private void SetScannerBehindT() {
+        buffer.setPos(t.pos);
+        NextCh();
+        line = t.line;
+        col = t.col;
+        charPos = t.charPos;
+        for (int i = 0; i < tlen; i++)
+            NextCh();
+    }
+
+    // get the next token (possibly a token already seen during peeking)
+    public Token Scan() {
+        if (tokens.next == null) {
+            return NextToken();
+        } else {
+            pt = tokens = tokens.next;
+            return tokens;
+        }
+    }
+
+    // get the next token, ignore pragmas
+    public Token Peek() {
+        do {
+            if (pt.next == null) {
+                pt.next = NextToken();
+            }
+            pt = pt.next;
+        } while (pt.kind > maxT); // skip pragmas
+
+        return pt;
+    }
+
+    // make sure that peeking starts at current scan position
+    public void ResetPeek() {
+        pt = tokens;
+    }
+
+} // end Scanner
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/DSLExpressionGenerator.java	Fri Jan 23 02:55:23 2015 +0100
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.expression.*;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Binary;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Call;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.DSLExpressionVisitor;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.IntLiteral;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public class DSLExpressionGenerator implements DSLExpressionVisitor {
+
+    private final Map<Variable, CodeTree> bindings;
+    private final CodeTree root;
+    private final Deque<CodeTree> stack = new ArrayDeque<>();
+
+    public DSLExpressionGenerator(CodeTree root, Map<Variable, CodeTree> bindings) {
+        this.bindings = bindings;
+        this.root = root;
+    }
+
+    public void visitBinary(Binary binary) {
+        CodeTree right = stack.pop();
+        CodeTree left = stack.pop();
+        stack.push(combine(left, string(" " + binary.getOperator() + " "), right));
+    }
+
+    public void visitCall(Call call) {
+        ExecutableElement method = call.getResolvedMethod();
+        CodeTree[] parameters = new CodeTree[method.getParameters().size()];
+        for (int i = 0; i < parameters.length; i++) {
+            parameters[parameters.length - i - 1] = pop();
+        }
+
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+
+        if (call.getReceiver() == null) {
+            if (isStatic(method)) {
+                builder.startStaticCall(method);
+            } else {
+                if (root != null) {
+                    builder.tree(root).string(".");
+                }
+                builder.startCall(method.getSimpleName().toString());
+            }
+        } else {
+            if (isStatic(method)) {
+                throw new AssertionError("Static calls must not have receivers.");
+            }
+            builder.startCall(pop(), method.getSimpleName().toString());
+        }
+        for (CodeTree parameter : parameters) {
+            builder.tree(parameter);
+        }
+        builder.end();
+
+        push(builder.build());
+    }
+
+    public void visitIntLiteral(IntLiteral binary) {
+        push(string(binary.getLiteral()));
+    }
+
+    public void visitNegate(Negate negate) {
+        push(combine(string("!"), pop()));
+    }
+
+    public void visitVariable(Variable variable) {
+        VariableElement resolvedVariable = variable.getResolvedVariable();
+        CodeTree tree;
+        if (variable.getReceiver() == null) {
+
+            if (isStatic(resolvedVariable)) {
+                tree = staticReference(resolvedVariable);
+            } else {
+                tree = bindings.get(variable);
+                boolean bound = true;
+                if (tree == null) {
+                    tree = string(resolvedVariable.getSimpleName().toString());
+                    bound = false;
+                }
+                if (root != null && !bound) {
+                    tree = combine(root, string("."), tree);
+                }
+            }
+        } else {
+            if (isStatic(resolvedVariable)) {
+                throw new AssertionError("Static variables cannot have receivers.");
+            }
+            tree = combine(pop(), string("."), string(resolvedVariable.getSimpleName().toString()));
+        }
+        push(tree);
+    }
+
+    private static boolean isStatic(Element element) {
+        return element.getModifiers().contains(Modifier.STATIC);
+    }
+
+    private static CodeTree combine(CodeTree tree1, CodeTree tree2) {
+        return new CodeTreeBuilder(null).startGroup().tree(tree1).tree(tree2).end().build();
+    }
+
+    private static CodeTree combine(CodeTree tree1, CodeTree tree2, CodeTree tree3) {
+        return new CodeTreeBuilder(null).startGroup().tree(tree1).tree(tree2).tree(tree3).end().build();
+    }
+
+    private static CodeTree string(String s) {
+        return CodeTreeBuilder.singleString(s);
+    }
+
+    private static CodeTree staticReference(VariableElement var) {
+        return CodeTreeBuilder.createBuilder().staticReference(var.asType(), var.getSimpleName().toString()).build();
+    }
+
+    private void push(CodeTree tree) {
+        stack.push(tree);
+    }
+
+    private CodeTree pop() {
+        return stack.pop();
+    }
+
+    public static CodeTree write(DSLExpression expression, CodeTree root, Map<Variable, CodeTree> bindings) {
+        DSLExpressionGenerator writer = new DSLExpressionGenerator(root, bindings);
+        expression.accept(writer);
+        return writer.pop();
+    }
+
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Fri Jan 23 02:55:23 2015 +0100
@@ -43,6 +43,8 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.nodes.Node.Child;
 import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.expression.*;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable;
 import com.oracle.truffle.dsl.processor.java.*;
 import com.oracle.truffle.dsl.processor.java.model.*;
 import com.oracle.truffle.dsl.processor.model.*;
@@ -51,7 +53,7 @@
 
 public class NodeGenFactory {
 
-    private static final String FRAME_VALUE = "frameValue";
+    private static final String FRAME_VALUE = TemplateMethod.FRAME_NAME;
 
     private static final String NAME_SUFFIX = "_";
 
@@ -318,7 +320,7 @@
         return constructor;
     }
 
-    private static boolean mayBeExcluded(SpecializationData specialization) {
+    public static boolean mayBeExcluded(SpecializationData specialization) {
         return !specialization.getExceptions().isEmpty() || !specialization.getExcludedBy().isEmpty();
     }
 
@@ -1061,7 +1063,7 @@
             return true;
         }
 
-        if (!fastPath && group.getSpecialization() != null && !group.getSpecialization().getExceptions().isEmpty()) {
+        if (!fastPath && group.getSpecialization() != null && mayBeExcluded(group.getSpecialization())) {
             return true;
         }
 
@@ -1438,7 +1440,7 @@
         List<GuardExpression> elseGuardExpressions = group.findElseConnectableGuards();
         List<GuardExpression> guardExpressions = new ArrayList<>(group.getGuards());
         guardExpressions.removeAll(elseGuardExpressions);
-        CodeTree methodGuards = createMethodGuardCheck(guardExpressions, currentValues);
+        CodeTree methodGuards = createMethodGuardCheck(guardExpressions, group.getSpecialization(), currentValues);
 
         if (!group.getAssumptions().isEmpty()) {
             if (execution.isFastPath() && !forType.isGeneric()) {
@@ -1533,14 +1535,13 @@
     }
 
     private boolean isTypeGuardUsedInAnyGuardBelow(SpecializationGroup group, LocalContext currentValues, TypeGuard typeGuard) {
-        NodeExecutionData execution = node.getChildExecutions().get(typeGuard.getSignatureIndex());
+        LocalVariable localVariable = currentValues.getValue(typeGuard.getSignatureIndex());
 
         for (GuardExpression guard : group.getGuards()) {
-            List<Parameter> guardParameters = guard.getResolvedGuard().findByExecutionData(execution);
-            TypeData sourceType = currentValues.getValue(typeGuard.getSignatureIndex()).getType();
-
-            for (Parameter guardParameter : guardParameters) {
-                if (sourceType.needsCastTo(guardParameter.getType())) {
+            Map<Variable, LocalVariable> boundValues = bindLocalValues(guard.getExpression(), group.getSpecialization(), currentValues);
+            for (Variable var : guard.getExpression().findBoundVariables()) {
+                LocalVariable target = boundValues.get(var);
+                if (localVariable.getName().equals(target.getName())) {
                     return true;
                 }
             }
@@ -1946,20 +1947,57 @@
         return builder.build();
     }
 
-    private CodeTree createMethodGuardCheck(List<GuardExpression> guardExpressions, LocalContext currentValues) {
+    private CodeTree createMethodGuardCheck(List<GuardExpression> guardExpressions, SpecializationData specialization, LocalContext currentValues) {
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
         String and = "";
         for (GuardExpression guard : guardExpressions) {
+            DSLExpression expression = guard.getExpression();
+            Map<Variable, LocalVariable> bindings = bindLocalValues(expression, specialization, currentValues);
+            Map<Variable, CodeTree> resolvedBindings = new HashMap<>();
+            for (Variable variable : bindings.keySet()) {
+                LocalVariable localVariable = bindings.get(variable);
+                CodeTree resolved = CodeTreeBuilder.singleString(localVariable.getName());
+                if (!ElementUtils.typeEquals(variable.getResolvedType(), localVariable.getTypeMirror())) {
+                    resolved = CodeTreeBuilder.createBuilder().cast(variable.getResolvedType(), resolved).build();
+                }
+                resolvedBindings.put(variable, resolved);
+            }
+
             builder.string(and);
-            if (guard.isNegated()) {
-                builder.string("!");
-            }
-            builder.tree(callTemplateMethod(accessParent(null), guard.getResolvedGuard(), currentValues));
+            builder.tree(DSLExpressionGenerator.write(expression, accessParent(null), resolvedBindings));
             and = " && ";
         }
         return builder.build();
     }
 
+    private static Map<Variable, LocalVariable> bindLocalValues(DSLExpression expression, SpecializationData specialization, LocalContext currentValues) throws AssertionError {
+        Map<Variable, LocalVariable> bindings = new HashMap<>();
+
+        List<Variable> boundVariables = expression.findBoundVariables();
+        if (specialization == null && !boundVariables.isEmpty()) {
+            throw new AssertionError("Cannot bind guard variable in non-specialization group. yet.");
+        }
+
+        // resolve bindings for local context
+        for (Variable variable : boundVariables) {
+            Parameter resolvedParameter = specialization.findByVariable(variable.getResolvedVariable());
+            if (resolvedParameter != null) {
+                LocalVariable localVariable;
+                if (resolvedParameter.getSpecification().isSignature()) {
+                    NodeExecutionData execution = resolvedParameter.getSpecification().getExecution();
+                    localVariable = currentValues.getValue(execution);
+                } else {
+                    localVariable = currentValues.get(resolvedParameter.getLocalName());
+                }
+                if (localVariable == null) {
+                    throw new AssertionError("Could not resolve local for execution.");
+                }
+                bindings.put(variable, localVariable);
+            }
+        }
+        return bindings;
+    }
+
     private CodeTree[] createTypeCheckAndCast(List<TypeGuard> typeGuards, Set<TypeGuard> castGuards, LocalContext currentValues, SpecializationExecution specializationExecution) {
         CodeTreeBuilder checksBuilder = CodeTreeBuilder.createBuilder();
         CodeTreeBuilder castsBuilder = CodeTreeBuilder.createBuilder();
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Fri Jan 23 02:55:23 2015 +0100
@@ -181,8 +181,17 @@
     }
 
     public static String getReadableSignature(ExecutableElement method) {
-        // TODO toString does not guarantee a good signature
-        return method.toString();
+        StringBuilder builder = new StringBuilder();
+        builder.append(method.getSimpleName().toString());
+        builder.append("(");
+        String sep = "";
+        for (VariableElement var : method.getParameters()) {
+            builder.append(sep);
+            builder.append(getSimpleName(var.asType()));
+            sep = ", ";
+        }
+        builder.append(")");
+        return builder.toString();
     }
 
     public static boolean hasError(TypeMirror mirror) {
@@ -680,6 +689,8 @@
                 return pack.getQualifiedName().toString();
             case ARRAY:
                 return getSimpleName(((ArrayType) mirror).getComponentType());
+            case EXECUTABLE:
+                return null;
             default:
                 throw new RuntimeException("Unknown type specified " + mirror.getKind());
         }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java	Fri Jan 23 02:55:23 2015 +0100
@@ -77,11 +77,11 @@
     }
 
     public static CodeTree singleString(String s) {
-        return new CodeTreeBuilder(null).string(s).getTree();
+        return createBuilder().string(s).build();
     }
 
     public static CodeTree singleType(TypeMirror s) {
-        return new CodeTreeBuilder(null).type(s).getTree();
+        return createBuilder().type(s).build();
     }
 
     private CodeTreeBuilder push(CodeTreeKind kind) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AssumptionExpression.java	Fri Jan 23 02:55:23 2015 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.expression.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public final class AssumptionExpression extends MessageContainer {
+
+    private final TemplateMethod source;
+    private final DSLExpression expression;
+
+    public AssumptionExpression(TemplateMethod source, DSLExpression expression) {
+        this.source = source;
+        this.expression = expression;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return source.getMessageElement();
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return source.getMessageAnnotation();
+    }
+
+    @Override
+    public AnnotationValue getMessageAnnotationValue() {
+        return ElementUtils.getAnnotationValue(getMessageAnnotation(), "assumptions");
+    }
+
+    public DSLExpression getExpression() {
+        return expression;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CacheExpression.java	Fri Jan 23 02:55:23 2015 +0100
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.expression.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public final class CacheExpression extends MessageContainer {
+
+    private final DSLExpression expression;
+    private final Parameter sourceParameter;
+    private final AnnotationMirror sourceAnnotationMirror;
+
+    public CacheExpression(Parameter sourceParameter, AnnotationMirror sourceAnnotationMirror, DSLExpression expression) {
+        this.sourceParameter = sourceParameter;
+        this.expression = expression;
+        this.sourceAnnotationMirror = sourceAnnotationMirror;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return sourceParameter.getVariableElement();
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return sourceAnnotationMirror;
+    }
+
+    @Override
+    public AnnotationValue getMessageAnnotationValue() {
+        return ElementUtils.getAnnotationValue(getMessageAnnotation(), "value");
+    }
+
+    public DSLExpression getExpression() {
+        return expression;
+    }
+
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java	Fri Jan 23 02:55:23 2015 +0100
@@ -85,8 +85,4 @@
         return super.equals(obj);
     }
 
-    public Parameter getFrame() {
-        return findParameter("frameValue");
-    }
-
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardData.java	Thu Jan 22 20:44:24 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import java.util.*;
-
-public class GuardData extends TemplateMethod {
-
-    private List<GuardExpression> impliesExpressions;
-
-    public GuardData(TemplateMethod method, List<GuardExpression> impliesExpressions) {
-        super(method);
-        this.impliesExpressions = impliesExpressions;
-    }
-
-    public List<GuardExpression> getImpliesExpressions() {
-        return impliesExpressions;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof GuardData) {
-            GuardData other = (GuardData) obj;
-            return getMethod().equals(other.getMethod());
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return getMethod().hashCode();
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java	Fri Jan 23 02:55:23 2015 +0100
@@ -24,120 +24,63 @@
 
 import java.util.*;
 
-public final class GuardExpression {
-
-    private GuardData resolvedGuard;
-    private NodeExecutionData[] resolvedChildren;
-
-    private final String guardName;
-    private final boolean negated;
-    private final String[] childNames;
+import javax.lang.model.element.*;
 
-    public GuardExpression(String expression, boolean allowArguments) {
-        String exp = expression;
-        if (exp.startsWith("!")) {
-            exp = exp.substring(1, exp.length());
-            negated = true;
-        } else {
-            negated = false;
-        }
+import com.oracle.truffle.dsl.processor.expression.*;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate;
+import com.oracle.truffle.dsl.processor.java.*;
 
-        int argumentStart = exp.indexOf('(');
-        int endIndex = exp.lastIndexOf(')');
-        if (allowArguments && argumentStart != -1 && endIndex != -1) {
-            guardName = exp.substring(0, argumentStart).trim();
-            String arguments = exp.substring(argumentStart + 1, endIndex);
-            String[] children = arguments.split(",");
-            for (int i = 0; i < children.length; i++) {
-                children[i] = children[i].trim();
-            }
-            if (children.length == 1 && children[0].isEmpty()) {
-                childNames = new String[0];
-            } else {
-                childNames = children;
-            }
-        } else {
-            guardName = exp;
-            childNames = null;
-        }
+public final class GuardExpression extends MessageContainer {
+
+    private final TemplateMethod source;
+    private final DSLExpression expression;
+
+    public GuardExpression(TemplateMethod source, DSLExpression expression) {
+        this.source = source;
+        this.expression = expression;
     }
 
-    public String[] getChildNames() {
-        return childNames;
-    }
-
-    public boolean isResolved() {
-        return resolvedGuard != null;
+    @Override
+    public Element getMessageElement() {
+        return source.getMessageElement();
     }
 
-    public String getGuardName() {
-        return guardName;
-    }
-
-    public NodeExecutionData[] getResolvedChildren() {
-        return resolvedChildren;
-    }
-
-    public void setResolvedChildren(NodeExecutionData[] resolvedChildren) {
-        this.resolvedChildren = resolvedChildren;
-    }
-
-    public void setResolvedGuard(GuardData guard) {
-        this.resolvedGuard = guard;
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return source.getMessageAnnotation();
     }
 
     @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
+    public AnnotationValue getMessageAnnotationValue() {
+        return ElementUtils.getAnnotationValue(getMessageAnnotation(), "guards");
+    }
+
+    public DSLExpression getExpression() {
+        return expression;
+    }
+
+    public boolean equalsNegated(GuardExpression other) {
+        boolean negated = false;
+        DSLExpression thisExpression = expression;
+        if (thisExpression instanceof Negate) {
+            negated = true;
+            thisExpression = ((Negate) thisExpression).getReceiver();
+        }
+
+        boolean otherNegated = false;
+        DSLExpression otherExpression = other.expression;
+        if (otherExpression instanceof Negate) {
+            otherNegated = true;
+            otherExpression = ((Negate) otherExpression).getReceiver();
+        }
+        return Objects.equals(thisExpression, otherExpression) && negated != otherNegated;
+    }
+
+    public boolean implies(GuardExpression other) {
+        if (Objects.equals(expression, other.expression)) {
             return true;
-        } else if (obj instanceof GuardExpression) {
-            GuardExpression other = (GuardExpression) obj;
-            if (isResolved() && other.isResolved()) {
-                return resolvedGuard.equals(other.resolvedGuard) && negated == other.negated && Arrays.equals(resolvedChildren, other.resolvedChildren);
-            } else {
-                boolean equal = guardName.equals(other.guardName) && negated == other.negated;
-                if (childNames != null && other.childNames != null) {
-                    equal &= Arrays.equals(childNames, other.childNames);
-                }
-                return equal;
-            }
         }
         return false;
     }
 
-    @Override
-    public int hashCode() {
-        return Objects.hash(guardName, negated, resolvedGuard, resolvedChildren);
-    }
-
-    public boolean implies(GuardExpression other) {
-        if (equals(other)) {
-            return true;
-        }
-
-        if (isResolved() && other.isResolved()) {
-            for (GuardExpression implies : getResolvedGuard().getImpliesExpressions()) {
-                if (implies.getGuardName().equals(other.getGuardName())) {
-                    if (implies.isNegated() == other.isNegated()) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return (negated ? "!" : "") + guardName;
-    }
-
-    public boolean isNegated() {
-        return negated;
-    }
-
-    public GuardData getResolvedGuard() {
-        return resolvedGuard;
-    }
-
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java	Fri Jan 23 02:55:23 2015 +0100
@@ -148,7 +148,7 @@
             if (!specialization.isReachable()) {
                 continue;
             }
-            if (specialization.isFrameUsedByGuard()) {
+            if (specialization.isFrameUsed()) {
                 return true;
             }
         }
@@ -239,7 +239,7 @@
     public boolean supportsFrame() {
         if (executableTypes != null) {
             for (ExecutableTypeData execType : getExecutableTypes(-1)) {
-                if (execType.findParameter("frameValue") == null) {
+                if (execType.findParameter(TemplateMethod.FRAME_NAME) == null) {
                     return false;
                 }
             }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java	Fri Jan 23 02:55:23 2015 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.dsl.processor.model;
 
+import javax.lang.model.element.*;
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.java.*;
@@ -36,6 +37,8 @@
     private final int typeVarArgsIndex;
     private final TypeMirror actualType;
 
+    private VariableElement variableElement;
+
     public Parameter(ParameterSpec specification, TypeMirror actualType, int specificationVarArgsIndex, int typeVarArgsIndex) {
         this.specification = specification;
         this.actualType = actualType;
@@ -67,6 +70,15 @@
         this.specificationVarArgsIndex = parameter.specificationVarArgsIndex;
         this.localName = parameter.localName;
         this.typeVarArgsIndex = parameter.typeVarArgsIndex;
+        this.variableElement = parameter.variableElement;
+    }
+
+    public void setVariableElement(VariableElement variableElement) {
+        this.variableElement = variableElement;
+    }
+
+    public VariableElement getVariableElement() {
+        return variableElement;
     }
 
     public int getTypeVarArgsIndex() {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java	Fri Jan 23 02:55:23 2015 +0100
@@ -24,8 +24,9 @@
 
 import java.util.*;
 
+import javax.lang.model.element.*;
+
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
 
 public final class SpecializationData extends TemplateMethod {
 
@@ -40,6 +41,8 @@
     private final SpecializationKind kind;
     private final List<SpecializationThrowsData> exceptions;
     private List<GuardExpression> guards = Collections.emptyList();
+    private List<CacheExpression> caches = Collections.emptyList();
+    private List<AssumptionExpression> assumptionExpressions = Collections.emptyList();
     private List<ShortCircuitData> shortCircuits;
     private List<String> assumptions = Collections.emptyList();
     private final Set<SpecializationData> contains = new TreeSet<>();
@@ -62,6 +65,15 @@
         }
     }
 
+    public Parameter findByVariable(VariableElement variable) {
+        for (Parameter parameter : getParameters()) {
+            if (parameter.getVariableElement() == variable) {
+                return parameter;
+            }
+        }
+        return null;
+    }
+
     public void setInsertBefore(SpecializationData insertBefore) {
         this.insertBefore = insertBefore;
     }
@@ -113,11 +125,7 @@
             sinks.addAll(exceptions);
         }
         if (guards != null) {
-            for (GuardExpression guard : guards) {
-                if (guard.isResolved()) {
-                    sinks.add(guard.getResolvedGuard());
-                }
-            }
+            sinks.addAll(guards);
         }
         return sinks;
     }
@@ -284,20 +292,24 @@
         return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature());
     }
 
-    public boolean isFrameUsedByGuard() {
-        for (GuardExpression guard : getGuards()) {
-            if (guard.getResolvedGuard() == null) {
-                continue;
-            }
+    public boolean isFrameUsed() {
+        return getFrame() != null;
+    }
+
+    public List<CacheExpression> getCaches() {
+        return caches;
+    }
 
-            for (Parameter param : guard.getResolvedGuard().getParameters()) {
-                if (ElementUtils.typeEquals(param.getType(), getNode().getFrameType())) {
-                    return true;
-                }
-            }
-        }
+    public void setCaches(List<CacheExpression> caches) {
+        this.caches = caches;
+    }
 
-        return false;
+    public void setAssumptionExpressions(List<AssumptionExpression> assumptionExpressions) {
+        this.assumptionExpressions = assumptionExpressions;
+    }
+
+    public List<AssumptionExpression> getAssumptionExpressions() {
+        return assumptionExpressions;
     }
 
     public boolean isReachableAfter(SpecializationData prev) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java	Fri Jan 23 02:55:23 2015 +0100
@@ -35,6 +35,7 @@
  */
 public class TemplateMethod extends MessageContainer implements Comparable<TemplateMethod> {
 
+    public static final String FRAME_NAME = "frameValue";
     public static final int NO_NATURAL_ORDER = -1;
 
     private String id;
@@ -68,6 +69,10 @@
         this.id = id;
     }
 
+    public final Parameter getFrame() {
+        return findParameter(FRAME_NAME);
+    }
+
     public String createReferenceName() {
         if (getMethod() == null) {
             return "-";
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java	Thu Jan 22 20:44:24 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-public class GuardParser extends NodeMethodParser<GuardData> {
-
-    private final GuardExpression expression;
-    private final TemplateMethod guardedMethod;
-
-    public GuardParser(ProcessorContext context, NodeData node, TemplateMethod compatibleSource, GuardExpression expression) {
-        super(context, node);
-        this.expression = expression;
-        this.guardedMethod = compatibleSource;
-        getParser().setEmitErrors(false);
-        setParseNullOnError(false);
-    }
-
-    @Override
-    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
-        return super.createValueParameterSpec(execution);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null);
-        spec.setIgnoreAdditionalSpecifications(true);
-        spec.getRequired().clear();
-
-        if (expression.getResolvedChildren() != null) {
-            for (NodeExecutionData execution : expression.getResolvedChildren()) {
-                List<Parameter> foundInGuardedMethod = guardedMethod.findByExecutionData(execution);
-                for (Parameter guardedParameter : foundInGuardedMethod) {
-                    spec.addRequired(createParameterSpec(guardedParameter));
-                }
-            }
-        } else {
-            for (Parameter parameter : guardedMethod.getRequiredParameters()) {
-                spec.addRequired(createParameterSpec(parameter));
-            }
-        }
-
-        return spec;
-    }
-
-    private ParameterSpec createParameterSpec(Parameter parameter) {
-        List<TypeMirror> typeMirrors = ElementUtils.getAssignableTypes(getContext(), parameter.getType());
-        Set<String> typeIds = new HashSet<>();
-        for (TypeMirror typeMirror : typeMirrors) {
-            typeIds.add(ElementUtils.getUniqueIdentifier(typeMirror));
-        }
-        if (parameter.getSpecification().isSignature()) {
-            typeIds.retainAll(getTypeSystem().getTypeIdentifiers());
-        }
-
-        return new ParameterSpec(parameter.getSpecification(), typeMirrors, typeIds);
-    }
-
-    @Override
-    protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
-        Set<TypeMirror> typeMirrors = new LinkedHashSet<>();
-        typeMirrors.addAll(nodeData.getTypeSystem().getPrimitiveTypeMirrors());
-        typeMirrors.addAll(nodeData.getTypeSystem().getBoxedTypeMirrors());
-        return new ArrayList<>(typeMirrors);
-    }
-
-    @Override
-    protected Set<String> nodeTypeIdentifiers(NodeData nodeData) {
-        return nodeData.getTypeSystem().getTypeIdentifiers();
-    }
-
-    @Override
-    protected ParameterSpec createReturnParameterSpec() {
-        return new ParameterSpec("returnType", getContext().getType(boolean.class));
-    }
-
-    @Override
-    public boolean isParsable(ExecutableElement method) {
-        return true;
-    }
-
-    @Override
-    public GuardData create(TemplateMethod method, boolean invalid) {
-        Implies impliesAnnotation = method.getMethod().getAnnotation(Implies.class);
-        String[] impliesExpressions = new String[0];
-        if (impliesAnnotation != null) {
-            impliesExpressions = impliesAnnotation.value();
-        }
-        List<GuardExpression> guardExpressions = new ArrayList<>();
-        for (String string : impliesExpressions) {
-            guardExpressions.add(new GuardExpression(string, false));
-        }
-        return new GuardData(method, guardExpressions);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return null;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java	Fri Jan 23 02:55:23 2015 +0100
@@ -81,7 +81,15 @@
             parameterTypes.add(var.asType());
         }
 
-        return parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, parameterTypes);
+        TemplateMethod templateMethod = parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, parameterTypes);
+        if (templateMethod != null) {
+            for (int i = 0; i < templateMethod.getParameters().size(); i++) {
+                if (i < method.getParameters().size()) {
+                    templateMethod.getParameters().get(i).setVariableElement(method.getParameters().get(i));
+                }
+            }
+        }
+        return templateMethod;
     }
 
     public TemplateMethod parseImpl(MethodSpec methodSpecification, int naturalOrder, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType,
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Fri Jan 23 02:55:23 2015 +0100
@@ -33,6 +33,7 @@
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.expression.*;
 import com.oracle.truffle.dsl.processor.java.*;
 import com.oracle.truffle.dsl.processor.java.compiler.*;
 import com.oracle.truffle.dsl.processor.model.*;
@@ -174,8 +175,10 @@
         return node;
     }
 
-    private ArrayList<Element> loadMembers(TypeElement templateType) {
-        return new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType));
+    private List<Element> loadMembers(TypeElement templateType) {
+        List<Element> members = new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType));
+
+        return members;
     }
 
     private boolean containsSpecializations(List<Element> elements) {
@@ -687,7 +690,11 @@
             return;
         }
 
-        initializeGuards(elements, node);
+        initializeExpressions(elements, node);
+        if (node.hasErrors()) {
+            return;
+        }
+
         initializeGeneric(node);
         initializeUninitialized(node);
         initializeOrder(node);
@@ -775,11 +782,11 @@
                         AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
                         if (foundSpecialization.compareTo(specialization) > 0) {
                             specialization.addError(value, "The contained specialization '%s' must be declared before the containing specialization.", includeName);
-                        } else {
-                            specialization.addError(value,
-                                            "The contained specialization '%s' is not fully compatible. The contained specialization must be strictly more generic than the containing one.",
-                                            includeName);
-                        }
+                        }/*
+                          * else { specialization.addError(value,
+                          * "The contained specialization '%s' is not fully compatible. The contained specialization must be strictly more generic than the containing one."
+                          * , includeName); }
+                          */
 
                     }
                     resolvedSpecializations.add(foundSpecialization);
@@ -925,74 +932,68 @@
         return changed;
     }
 
-    private void initializeGuards(List<? extends Element> elements, NodeData node) {
-        Map<String, List<ExecutableElement>> potentialGuards = new HashMap<>();
-        for (SpecializationData specialization : node.getSpecializations()) {
-            for (GuardExpression exp : specialization.getGuards()) {
-                potentialGuards.put(exp.getGuardName(), null);
-            }
-        }
+    private void initializeExpressions(List<? extends Element> elements, NodeData node) {
+        List<Element> members = filterNotAccessibleElements(node.getTemplateType(), elements);
 
-        TypeMirror booleanType = context.getType(boolean.class);
-        for (ExecutableElement potentialGuard : ElementFilter.methodsIn(elements)) {
-            if (potentialGuard.getModifiers().contains(Modifier.PRIVATE)) {
-                continue;
-            }
-            String methodName = potentialGuard.getSimpleName().toString();
-            if (!potentialGuards.containsKey(methodName)) {
-                continue;
-            }
+        final TypeMirror booleanType = context.getType(boolean.class);
 
-            if (!ElementUtils.typeEquals(potentialGuard.getReturnType(), booleanType)) {
+        for (SpecializationData specialization : node.getSpecializations()) {
+            if (specialization.getMethod() == null) {
                 continue;
             }
 
-            List<ExecutableElement> potentialMethods = potentialGuards.get(methodName);
-            if (potentialMethods == null) {
-                potentialMethods = new ArrayList<>();
-                potentialGuards.put(methodName, potentialMethods);
+            List<Element> specializationMembers = new ArrayList<>();
+            for (Parameter p : specialization.getParameters()) {
+                VariableElement variableElement = p.getVariableElement();
+                if (variableElement == null) {
+                    throw new AssertionError("All parameters must be resolved for " + specialization);
+                }
+
+                specializationMembers.add(variableElement);
             }
-            potentialMethods.add(potentialGuard);
-        }
+            specializationMembers.addAll(members);
 
-        for (SpecializationData specialization : node.getSpecializations()) {
-            for (GuardExpression exp : specialization.getGuards()) {
-                resolveGuardExpression(node, specialization, potentialGuards, exp);
+            DSLExpressionResolver resolver = new DSLExpressionResolver(context, specializationMembers);
+            List<String> guardDefinitions = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards");
+            List<GuardExpression> guardExpressions = new ArrayList<>();
+            for (String guard : guardDefinitions) {
+                GuardExpression guardExpression;
+                DSLExpression expression = null;
+                try {
+                    expression = DSLExpression.parse(guard);
+                    expression.accept(resolver);
+                    guardExpression = new GuardExpression(specialization, expression);
+                    if (!ElementUtils.typeEquals(expression.getResolvedType(), booleanType)) {
+                        guardExpression.addError("Incompatible return type %s. Guard expressions must return boolean.", ElementUtils.getSimpleName(expression.getResolvedType()));
+                    }
+// guardExpression.addWarning("Expression:%s", expression.toString());
+                } catch (InvalidExpressionException e) {
+                    guardExpression = new GuardExpression(specialization, null);
+                    guardExpression.addError("Error parsing expression '%s': %s", guard, e.getMessage());
+                }
+                guardExpressions.add(guardExpression);
             }
+            specialization.setGuards(guardExpressions);
         }
     }
 
-    private void resolveGuardExpression(NodeData node, TemplateMethod source, Map<String, List<ExecutableElement>> guards, GuardExpression expression) {
-        List<ExecutableElement> availableGuards = guards.get(expression.getGuardName());
-        if (availableGuards == null) {
-            source.addError("No compatible guard with method name '%s' found.", expression.getGuardName());
-            return;
-        }
+    private static List<Element> filterNotAccessibleElements(TypeElement templateType, List<? extends Element> elements) {
+        String packageName = ElementUtils.getPackageName(templateType);
+        List<Element> filteredElements = new ArrayList<>(elements);
+        for (Element element : elements) {
+            Modifier visibility = ElementUtils.getVisibility(element.getModifiers());
+            if (visibility == Modifier.PRIVATE) {
+                continue;
+            } else if (visibility == null) {
+                String elementPackageName = ElementUtils.getPackageName(element.getEnclosingElement().asType());
+                if (!Objects.equals(packageName, elementPackageName) && !elementPackageName.equals("java.lang")) {
+                    continue;
+                }
+            }
 
-        String[] childNames = expression.getChildNames();
-        if (childNames != null) {
-            NodeExecutionData[] resolvedExecutions = new NodeExecutionData[childNames.length];
-            for (int i = 0; i < childNames.length; i++) {
-                String childName = childNames[i];
-                NodeExecutionData execution = node.findExecutionByExpression(childName);
-                if (execution == null) {
-                    source.addError("Guard parameter '%s' for guard '%s' could not be mapped to a declared child node.", childName, expression.getGuardName());
-                    return;
-                }
-                resolvedExecutions[i] = execution;
-            }
-            expression.setResolvedChildren(resolvedExecutions);
+            filteredElements.add(element);
         }
-
-        GuardParser parser = new GuardParser(context, node, source, expression);
-        List<GuardData> matchingGuards = parser.parse(availableGuards);
-        if (!matchingGuards.isEmpty() && matchingGuards.get(0) != null) {
-            expression.setResolvedGuard(matchingGuards.get(0));
-        } else {
-            MethodSpec spec = parser.createSpecification(source.getMethod(), source.getMarkerAnnotation());
-            spec.applyTypeDefinitions("types");
-            source.addError("No guard with name '%s' matched the required signature. Expected signature: %n%s", expression.getGuardName(), spec.toSignatureString("guard"));
-        }
+        return filteredElements;
     }
 
     private void initializeGeneric(final NodeData node) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java	Fri Jan 23 02:55:23 2015 +0100
@@ -24,9 +24,7 @@
 
 import java.util.*;
 
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.generator.*;
 import com.oracle.truffle.dsl.processor.model.*;
 import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature;
 
@@ -110,18 +108,35 @@
             return null;
         }
 
+        if (previous.mayBeExcluded()) {
+            return null;
+        }
+
         /* Guard is else branch can be connected in previous specialization. */
         if (elseConnectedGuards.contains(guard)) {
             return guard;
         }
 
         GuardExpression previousGuard = previous.getGuards().get(elseConnectedGuards.size());
-        if (guard.getResolvedGuard().getMethod().equals(previousGuard.getResolvedGuard().getMethod()) && guard.isNegated() != previousGuard.isNegated()) {
+        if (guard.equalsNegated(previousGuard)) {
             return guard;
         }
         return null;
     }
 
+    private boolean mayBeExcluded() {
+        if (specialization != null) {
+            return NodeGenFactory.mayBeExcluded(specialization);
+        } else {
+            for (SpecializationGroup group : getChildren()) {
+                if (group.mayBeExcluded()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     private void updateChildren(List<SpecializationGroup> childs) {
         if (!children.isEmpty()) {
             children.clear();
@@ -204,38 +219,10 @@
         // check for guards for required type casts
         for (Iterator<GuardExpression> iterator = guardMatches.iterator(); iterator.hasNext();) {
             GuardExpression guardMatch = iterator.next();
-
-            int signatureIndex = 0;
-            for (Parameter parameter : guardMatch.getResolvedGuard().getParameters()) {
-                signatureIndex++;
-                if (!parameter.getSpecification().isSignature()) {
-                    continue;
-                }
-
-                TypeMirror guardType = parameter.getType();
-
-                // object guards can be safely moved up
-                if (ElementUtils.isObject(guardType)) {
-                    continue;
-                }
-
-                // generic guards can be safely moved up
-                SpecializationData generic = first.node.getGenericSpecialization();
-                if (generic != null) {
-                    Parameter genericParameter = generic.findParameter(parameter.getLocalName());
-                    if (genericParameter != null && ElementUtils.typeEquals(genericParameter.getType(), guardType)) {
-                        continue;
-                    }
-                }
-
-                // signature index required for moving up guards
-                if (containsIndex(typeGuardsMatches, signatureIndex) || (first.getParent() != null && first.getParent().containsTypeGuardIndex(signatureIndex))) {
-                    continue;
-                }
-
+            if (!guardMatch.getExpression().findBoundVariables().isEmpty()) {
                 iterator.remove();
-                break;
             }
+            // TODO we need to be smarter here with bound parameters.
         }
 
         if (assumptionMatches.isEmpty() && typeGuardsMatches.isEmpty() && guardMatches.isEmpty()) {
@@ -252,25 +239,6 @@
         return new SpecializationGroup(newChildren, assumptionMatches, typeGuardsMatches, guardMatches);
     }
 
-    private boolean containsTypeGuardIndex(int index) {
-        if (containsIndex(typeGuards, index)) {
-            return true;
-        }
-        if (parent != null) {
-            return parent.containsTypeGuardIndex(index);
-        }
-        return false;
-    }
-
-    private static boolean containsIndex(List<TypeGuard> typeGuards, int signatureIndex) {
-        for (TypeGuard guard : typeGuards) {
-            if (guard.signatureIndex == signatureIndex) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     public static SpecializationGroup create(SpecializationData specialization) {
         return new SpecializationGroup(specialization);
     }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java	Thu Jan 22 20:44:24 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java	Fri Jan 23 02:55:23 2015 +0100
@@ -92,13 +92,6 @@
             specialization.setInsertBeforeName(insertBeforeName);
         }
 
-        List<String> guardDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards");
-        List<GuardExpression> guardExpressions = new ArrayList<>();
-        for (String guardDef : guardDefs) {
-            guardExpressions.add(new GuardExpression(guardDef, true));
-        }
-        specialization.setGuards(guardExpressions);
-
         List<String> containsDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "contains");
         Set<String> containsNames = specialization.getContainsNames();
         containsNames.clear();