changeset 16851:2db61eddcb97

Truffle-DSL: argument syntax support for guards
author Christian Humer <christian.humer@gmail.com>
date Mon, 18 Aug 2014 18:41:16 +0200
parents d6c002f4d2a9
children 3c114b3e08c3
files 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/MethodGuardsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.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/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/NodeExecutionData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.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/model/TemplateMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.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/NodeExecutionData.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 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java
diffstat 19 files changed, 978 insertions(+), 532 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java	Mon Aug 18 17:44:42 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java	Mon Aug 18 18:41:16 2014 +0200
@@ -46,25 +46,25 @@
     @ImportGuards(Imports0.class)
     static class ImportGuards1 extends ValueNode {
 
-        @ExpectError("No compatible guard with method name 'nonStaticGuard' found. Please note that all signature types of the method guard must be declared in the type system.")
+        @ExpectError("No compatible guard with method name 'nonStaticGuard' found.")
         @Specialization(guards = "nonStaticGuard")
         int f1(int a) {
             return a;
         }
 
-        @ExpectError("No compatible guard with method name 'protectedGuard' found. Please note that all signature types of the method guard must be declared in the type system.")
+        @ExpectError("No compatible guard with method name 'protectedGuard' found.")
         @Specialization(guards = "protectedGuard")
         int f2(int a) {
             return a;
         }
 
-        @ExpectError("No compatible guard with method name 'packageGuard' found. Please note that all signature types of the method guard must be declared in the type system.")
+        @ExpectError("No compatible guard with method name 'packageGuard' found.")
         @Specialization(guards = "packageGuard")
         int f3(int a) {
             return a;
         }
 
-        @ExpectError("No compatible guard with method name 'privateGuard' found. Please note that all signature types of the method guard must be declared in the type system.")
+        @ExpectError("No compatible guard with method name 'privateGuard' found.")
         @Specialization(guards = "privateGuard")
         int f4(int a) {
             return a;
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java	Mon Aug 18 17:44:42 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java	Mon Aug 18 18:41:16 2014 +0200
@@ -142,7 +142,7 @@
         }
 
         @Specialization(guards = "baseGuard")
-        @ExpectError("No compatible guard with method name 'baseGuard' found. Please note that all signature types of the method guard must be declared in the type system.")
+        @ExpectError("No guard with name 'baseGuard' matched the required signature.%")
         int doSpecialized(String value0) {
             return 42;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java	Mon Aug 18 18:41:16 2014 +0200
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2012, 2013, 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.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArguments0Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArguments1Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble0Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble1Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble2Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble3Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsSingle2Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class MethodGuardsWithArgumentsTest {
+
+    @Test
+    public void testMArguments0() {
+        TestRootNode<MArguments0> root = createRoot(MArguments0Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root));
+    }
+
+    abstract static class MArguments0 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @Specialization(guards = "guard()")
+        int do1() {
+            return 42;
+        }
+    }
+
+    @Test
+    public void testMArguments1() {
+        TestRootNode<MArguments1> root = createRoot(MArguments1Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root));
+    }
+
+    abstract static class MArguments1 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @Specialization(guards = "guard ()")
+        int do1() {
+            return 42;
+        }
+    }
+
+    @Test
+    public void testMArgumentsSingle0() {
+        TestRootNode<MArguments1> root = createRoot(MArguments1Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("a")
+    abstract static class MArgumentsSingle0 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @Specialization(guards = "guard()")
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsSingle1() {
+        TestRootNode<MArguments1> root = createRoot(MArguments1Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("a")
+    abstract static class MArgumentsSingle1 extends ValueNode {
+
+        static boolean guard(int a) {
+            return a == 42;
+        }
+
+        @Specialization(guards = "guard(a)")
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsSingle2() {
+        TestRootNode<MArgumentsSingle2> root = createRoot(MArgumentsSingle2Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("a")
+    abstract static class MArgumentsSingle2 extends ValueNode {
+
+        static boolean guard(int a1, int a2) {
+            return a1 == 42 && a2 == 42;
+        }
+
+        @Specialization(guards = "guard(a,a)")
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsDouble0() {
+        TestRootNode<MArgumentsDouble0> root = createRoot(MArgumentsDouble0Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42, 0));
+    }
+
+    @NodeChild("a")
+    abstract static class MArgumentsDouble0 extends ValueNode {
+
+        static boolean guard(int a1, Object a2) {
+            return a1 == 42 && a2.equals(new Integer(42));
+        }
+
+        @Specialization(guards = "guard(a,a)")
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsDouble1() {
+        TestRootNode<MArgumentsDouble1> root = createRoot(MArgumentsDouble1Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42, 41));
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class MArgumentsDouble1 extends ValueNode {
+
+        static boolean guard(int a1, double a2) {
+            return a1 == 42 && a2 == 41;
+        }
+
+        @Specialization(guards = "guard(a,b)")
+        int do1(int a, @SuppressWarnings("unused") double b) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsDouble2() {
+        TestRootNode<MArgumentsDouble2> root = createRoot(MArgumentsDouble2Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42, 41.0));
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class MArgumentsDouble2 extends ValueNode {
+
+        static boolean guard(double a1, int a2) {
+            return a1 == 41 && a2 == 42;
+        }
+
+        @Specialization(guards = "guard(b,a)")
+        int do1(int a, @SuppressWarnings("unused") double b) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsDouble3() {
+        TestRootNode<MArgumentsDouble3> root = createRoot(MArgumentsDouble3Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42, 41.0));
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class MArgumentsDouble3 extends ValueNode {
+
+        static boolean guard(Object a1, double a2) {
+            return new Double(41.0).equals(a1) && a2 == 41;
+        }
+
+        @Specialization(guards = "guard(b,b)")
+        int do1(int a, @SuppressWarnings("unused") double b) {
+            return a;
+        }
+    }
+
+    abstract static class MArgumentsError0 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @ExpectError("No compatible guard with method name 'guard(' found.%")
+        @Specialization(guards = "guard(")
+        int do1() {
+            return 42;
+        }
+    }
+
+    abstract static class MArgumentsError1 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @ExpectError("No compatible guard with method name 'guard)' found.%")
+        @Specialization(guards = "guard)")
+        int do1() {
+            return 42;
+        }
+
+    }
+
+    abstract static class MArgumentsError2 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @ExpectError("Guard parameter 'a' for guard 'guard' could not be mapped to a declared child node.")
+        @Specialization(guards = "guard(a)")
+        int do1() {
+            return 42;
+        }
+    }
+
+    @NodeChild("b")
+    abstract static class MArgumentsError3 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @ExpectError("Guard parameter 'a' for guard 'guard' could not be mapped to a declared child node.")
+        @Specialization(guards = "guard(a)")
+        int do1(int b) {
+            return b;
+        }
+    }
+
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java	Mon Aug 18 17:44:42 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java	Mon Aug 18 18:41:16 2014 +0200
@@ -322,12 +322,12 @@
     /**
      * <pre>
      * variant1 $condition != null
-     * 
+     *
      * $type $name = defaultValue($type);
      * if ($condition) {
      *     $name = $value;
      * }
-     * 
+     *
      * variant2 $condition != null
      * $type $name = $value;
      * </pre>
@@ -1590,12 +1590,16 @@
         }
 
         private boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardExpression guard) {
-            int signatureIndex = 0;
             for (Parameter parameter : guard.getResolvedGuard().getParameters()) {
                 if (!parameter.getSpecification().isSignature()) {
                     continue;
                 }
 
+                int signatureIndex = source.getNode().getChildExecutions().indexOf(parameter.getSpecification().getExecution());
+                if (signatureIndex == -1) {
+                    continue;
+                }
+
                 TypeGuard typeGuard = group.findTypeGuard(signatureIndex);
                 if (typeGuard != null) {
                     TypeData requiredType = typeGuard.getType();
@@ -1609,8 +1613,6 @@
                         return true;
                     }
                 }
-
-                signatureIndex++;
             }
             return false;
         }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Mon Aug 18 17:44:42 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Mon Aug 18 18:41:16 2014 +0200
@@ -530,7 +530,7 @@
     public static boolean isEnclosedIn(Element enclosedIn, Element element) {
         if (element == null) {
             return false;
-        } else if (enclosedIn.equals(element)) {
+        } else if (typeEquals(enclosedIn.asType(), element.asType())) {
             return true;
         } else {
             return isEnclosedIn(enclosedIn, element.getEnclosingElement());
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java	Mon Aug 18 17:44:42 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java	Mon Aug 18 18:41:16 2014 +0200
@@ -27,18 +27,43 @@
 public final class GuardExpression {
 
     private GuardData resolvedGuard;
+    private NodeExecutionData[] resolvedChildren;
 
     private final String guardName;
     private final boolean negated;
+    private final String[] childNames;
 
-    public GuardExpression(String expression) {
-        if (expression.startsWith("!")) {
-            guardName = expression.substring(1, expression.length());
+    public GuardExpression(String expression, boolean allowArguments) {
+        String exp = expression;
+        if (exp.startsWith("!")) {
+            exp = exp.substring(1, exp.length());
             negated = true;
         } else {
-            guardName = expression;
             negated = false;
         }
+
+        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 String[] getChildNames() {
+        return childNames;
     }
 
     public boolean isResolved() {
@@ -49,18 +74,32 @@
         return guardName;
     }
 
-    public void setGuard(GuardData guard) {
+    public NodeExecutionData[] getResolvedChildren() {
+        return resolvedChildren;
+    }
+
+    public void setResolvedChildren(NodeExecutionData[] resolvedChildren) {
+        this.resolvedChildren = resolvedChildren;
+    }
+
+    public void setResolvedGuard(GuardData guard) {
         this.resolvedGuard = guard;
     }
 
     @Override
     public boolean equals(Object obj) {
-        if (obj instanceof GuardExpression) {
+        if (this == obj) {
+            return true;
+        } else if (obj instanceof GuardExpression) {
             GuardExpression other = (GuardExpression) obj;
             if (isResolved() && other.isResolved()) {
-                return resolvedGuard.equals(other.resolvedGuard) && negated == other.negated;
+                return resolvedGuard.equals(other.resolvedGuard) && negated == other.negated && Arrays.equals(resolvedChildren, other.resolvedChildren);
             } else {
-                return guardName.equals(other.guardName) && negated == other.negated;
+                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;
@@ -68,18 +107,13 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(guardName, negated, resolvedGuard);
+        return Objects.hash(guardName, negated, resolvedGuard, resolvedChildren);
     }
 
     public final boolean implies(GuardExpression other) {
-        if (other == this) {
+        if (equals(other)) {
             return true;
         }
-        if (getGuardName().equals(other.getGuardName())) {
-            if (isNegated() == other.isNegated()) {
-                return true;
-            }
-        }
 
         if (isResolved() && other.isResolved()) {
             for (GuardExpression implies : getResolvedGuard().getImpliesExpressions()) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java	Mon Aug 18 17:44:42 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java	Mon Aug 18 18:41:16 2014 +0200
@@ -30,7 +30,6 @@
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.java.*;
 import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
-import com.oracle.truffle.dsl.processor.parser.*;
 
 public class NodeData extends Template implements Comparable<NodeData> {
 
@@ -208,6 +207,30 @@
         return true;
     }
 
+    public NodeExecutionData findExecutionByExpression(String childNameExpression) {
+        String childName = childNameExpression;
+        int index = -1;
+
+        int start = childName.indexOf('[');
+        int end = childName.lastIndexOf(']');
+        if (start != -1 && end != -1 && start < end) {
+            try {
+                index = Integer.parseInt(childName.substring(start + 1, end));
+                childName = childName.substring(0, start);
+                childName = NodeExecutionData.createName(childName, index);
+            } catch (NumberFormatException e) {
+                // ignore
+            }
+        }
+
+        for (NodeExecutionData execution : childExecutions) {
+            if (execution.getName().equals(childName) && (execution.getIndex() == -1 || execution.getIndex() == index)) {
+                return execution;
+            }
+        }
+        return null;
+    }
+
     public List<NodeData> getNodeDeclaringChildren() {
         List<NodeData> nodeChildren = new ArrayList<>();
         for (NodeData child : getEnclosingNodes()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java	Mon Aug 18 18:41:16 2014 +0200
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 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.type.*;
+
+import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
+
+public class NodeExecutionData {
+
+    private final NodeChildData child;
+    private final String name;
+    private final int index;
+    private final boolean shortCircuit;
+
+    public NodeExecutionData(NodeChildData child, int index, boolean shortCircuit) {
+        this.child = child;
+        this.index = index;
+        this.shortCircuit = shortCircuit;
+        this.name = createName();
+    }
+
+    private String createName() {
+        return createName(child.getName(), index);
+    }
+
+    public TypeMirror getNodeType() {
+        TypeMirror type;
+        if (child.getCardinality() == Cardinality.MANY && child.getNodeType().getKind() == TypeKind.ARRAY) {
+            type = ((ArrayType) child.getNodeType()).getComponentType();
+        } else {
+            type = child.getNodeType();
+        }
+        return type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public NodeChildData getChild() {
+        return child;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public boolean isIndexed() {
+        return index > -1;
+    }
+
+    public boolean isShortCircuit() {
+        return shortCircuit;
+    }
+
+    public String getShortCircuitId() {
+        return createShortCircuitId(child, index);
+    }
+
+    public static String createShortCircuitId(NodeChildData child, int varArgsIndex) {
+        String shortCircuitName = child.getName();
+        if (child.getCardinality().isMany()) {
+            shortCircuitName = shortCircuitName + "[" + varArgsIndex + "]";
+        }
+        return shortCircuitName;
+    }
+
+    public static String createName(String childName, int index) {
+        if (index > -1) {
+            return childName + index;
+        }
+        return childName;
+    }
+
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java	Mon Aug 18 17:44:42 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java	Mon Aug 18 18:41:16 2014 +0200
@@ -28,7 +28,6 @@
 
 import com.oracle.truffle.dsl.processor.java.*;
 import com.oracle.truffle.dsl.processor.model.MethodSpec.TypeDef;
-import com.oracle.truffle.dsl.processor.parser.*;
 
 public class ParameterSpec {
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java	Mon Aug 18 17:44:42 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java	Mon Aug 18 18:41:16 2014 +0200
@@ -163,6 +163,17 @@
         return foundParameters;
     }
 
+    public List<Parameter> findByExecutionData(NodeExecutionData execution) {
+        List<Parameter> foundParameters = new ArrayList<>();
+        for (Parameter parameter : getParameters()) {
+            ParameterSpec spec = parameter.getSpecification();
+            if (spec != null && spec.getExecution() != null && spec.getExecution().equals(execution) && parameter.getSpecification().isSignature()) {
+                foundParameters.add(parameter);
+            }
+        }
+        return foundParameters;
+    }
+
     public Parameter findParameter(String valueName) {
         for (Parameter param : getReturnTypeAndParameters()) {
             if (param.getLocalName().equals(valueName)) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethodParser.java	Mon Aug 18 17:44:42 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,357 +0,0 @@
-/*
- * Copyright (c) 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 static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-
-import java.lang.annotation.*;
-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.java.*;
-
-public abstract class TemplateMethodParser<T extends Template, E extends TemplateMethod> {
-
-    private final ProcessorContext context;
-
-    protected final T template;
-
-    private boolean emitErrors = true;
-    private boolean parseNullOnError = false;
-    private boolean useVarArgs = false;
-
-    public TemplateMethodParser(ProcessorContext context, T template) {
-        this.template = template;
-        this.context = context;
-    }
-
-    protected void setUseVarArgs(boolean useVarArgs) {
-        this.useVarArgs = useVarArgs;
-    }
-
-    public boolean isUseVarArgs() {
-        return useVarArgs;
-    }
-
-    public boolean isEmitErrors() {
-        return emitErrors;
-    }
-
-    public void setParseNullOnError(boolean nullOnError) {
-        this.parseNullOnError = nullOnError;
-    }
-
-    public boolean isParseNullOnError() {
-        return parseNullOnError;
-    }
-
-    public void setEmitErrors(boolean emitErrors) {
-        this.emitErrors = emitErrors;
-    }
-
-    public ProcessorContext getContext() {
-        return context;
-    }
-
-    public TypeSystemData getTypeSystem() {
-        return template.getTypeSystem();
-    }
-
-    public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror);
-
-    public abstract E create(TemplateMethod method, boolean invalid);
-
-    public abstract boolean isParsable(ExecutableElement method);
-
-    public Class<? extends Annotation> getAnnotationType() {
-        return null;
-    }
-
-    public final List<E> parse(List<? extends Element> elements) {
-        List<ExecutableElement> methods = new ArrayList<>();
-        methods.addAll(ElementFilter.methodsIn(elements));
-
-        List<E> parsedMethods = new ArrayList<>();
-        boolean valid = true;
-        int naturalOrder = 0;
-        for (ExecutableElement method : methods) {
-            if (!isParsable(method)) {
-                continue;
-            }
-
-            Class<? extends Annotation> annotationType = getAnnotationType();
-            AnnotationMirror mirror = null;
-            if (annotationType != null) {
-                mirror = ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType);
-            }
-
-            E parsedMethod = parse(naturalOrder, method, mirror);
-
-            if (method.getModifiers().contains(Modifier.PRIVATE) && emitErrors) {
-                parsedMethod.addError("Method annotated with @%s must not be private.", getAnnotationType().getSimpleName());
-                parsedMethods.add(parsedMethod);
-                valid = false;
-                continue;
-            }
-
-            if (parsedMethod != null) {
-                parsedMethods.add(parsedMethod);
-            } else {
-                valid = false;
-            }
-            naturalOrder++;
-        }
-        Collections.sort(parsedMethods);
-
-        if (!valid && parseNullOnError) {
-            return null;
-        }
-        return parsedMethods;
-    }
-
-    private E parse(int naturalOrder, ExecutableElement method, AnnotationMirror annotation) {
-        MethodSpec methodSpecification = createSpecification(method, annotation);
-        if (methodSpecification == null) {
-            return null;
-        }
-
-        methodSpecification.applyTypeDefinitions("types");
-
-        String id = method.getSimpleName().toString();
-        TypeMirror returnType = method.getReturnType();
-        List<TypeMirror> parameterTypes = new ArrayList<>();
-        for (VariableElement var : method.getParameters()) {
-            parameterTypes.add(var.asType());
-        }
-
-        return parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, parameterTypes);
-    }
-
-    private E parseImpl(MethodSpec methodSpecification, int naturalOrder, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType, List<TypeMirror> parameterTypes) {
-        ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
-        Parameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, -1, -1);
-        if (returnTypeMirror == null) {
-            if (emitErrors) {
-                E invalidMethod = create(new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<Parameter> emptyList()), true);
-                String expectedReturnType = returnTypeSpec.toSignatureString(true);
-                String actualReturnType = ElementUtils.getSimpleName(returnType);
-
-                String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
-                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
-                invalidMethod.addError(message);
-                return invalidMethod;
-            } else {
-                return null;
-            }
-        }
-
-        List<Parameter> parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method != null ? method.isVarArgs() : false);
-        if (parameters == null) {
-            if (isEmitErrors() && method != null) {
-                E invalidMethod = create(new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<Parameter> emptyList()), true);
-                String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(method),
-                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
-                invalidMethod.addError(message);
-                return invalidMethod;
-            } else {
-                return null;
-            }
-        }
-
-        return create(new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, parameters), false);
-    }
-
-    private static String createActualSignature(ExecutableElement method) {
-        StringBuilder b = new StringBuilder("(");
-        String sep = "";
-        if (method != null) {
-            for (VariableElement var : method.getParameters()) {
-                b.append(sep);
-                b.append(ElementUtils.getSimpleName(var.asType()));
-                sep = ", ";
-            }
-        }
-        b.append(")");
-        return b.toString();
-    }
-
-    /*
-     * Parameter parsing tries to parse required arguments starting from offset 0 with increasing
-     * offset until it finds a signature end that matches the required specification. If there is no
-     * end matching the required arguments, parsing fails. Parameters prior to the parsed required
-     * ones are cut and used to parse the optional parameters.
-     */
-    private List<Parameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes, boolean varArgs) {
-        List<Parameter> parsedRequired = null;
-        int offset = 0;
-        for (; offset <= parameterTypes.size(); offset++) {
-            List<TypeMirror> parameters = new ArrayList<>();
-            parameters.addAll(parameterTypes.subList(offset, parameterTypes.size()));
-            parsedRequired = parseParametersRequired(spec, parameters, varArgs);
-            if (parsedRequired != null) {
-                break;
-            }
-        }
-
-        if (parsedRequired == null) {
-            return null;
-        }
-
-        if (parsedRequired.isEmpty() && offset == 0) {
-            offset = parameterTypes.size();
-        }
-        List<TypeMirror> potentialOptionals = parameterTypes.subList(0, offset);
-        List<Parameter> parsedOptionals = parseParametersOptional(spec, potentialOptionals);
-        if (parsedOptionals == null) {
-            return null;
-        }
-
-        List<Parameter> finalParameters = new ArrayList<>();
-        finalParameters.addAll(parsedOptionals);
-        finalParameters.addAll(parsedRequired);
-        return finalParameters;
-    }
-
-    private List<Parameter> parseParametersOptional(MethodSpec spec, List<TypeMirror> types) {
-        List<Parameter> parsedParams = new ArrayList<>();
-
-        int typeStartIndex = 0;
-        List<ParameterSpec> specifications = spec.getOptional();
-        outer: for (int specIndex = 0; specIndex < specifications.size(); specIndex++) {
-            ParameterSpec specification = specifications.get(specIndex);
-            for (int typeIndex = typeStartIndex; typeIndex < types.size(); typeIndex++) {
-                TypeMirror actualType = types.get(typeIndex);
-                Parameter optionalParam = matchParameter(specification, actualType, -1, -1);
-                if (optionalParam != null) {
-                    parsedParams.add(optionalParam);
-                    typeStartIndex = typeIndex + 1;
-                    continue outer;
-                }
-            }
-        }
-
-        if (typeStartIndex < types.size()) {
-            // not enough types found
-            return null;
-        }
-        return parsedParams;
-    }
-
-    private List<Parameter> parseParametersRequired(MethodSpec spec, List<TypeMirror> types, boolean typeVarArgs) {
-        List<Parameter> parsedParams = new ArrayList<>();
-        List<ParameterSpec> specifications = spec.getRequired();
-        boolean specVarArgs = spec.isVariableRequiredParameters();
-        int typeIndex = 0;
-        int specificationIndex = 0;
-
-        ParameterSpec specification;
-        while ((specification = nextSpecification(specifications, specificationIndex, specVarArgs)) != null) {
-            TypeMirror actualType = nextActualType(types, typeIndex, typeVarArgs);
-            if (actualType == null) {
-                if (spec.isIgnoreAdditionalSpecifications()) {
-                    break;
-                }
-                return null;
-            }
-
-            int typeVarArgsIndex = typeVarArgs ? typeIndex - types.size() + 1 : -1;
-            int specVarArgsIndex = specVarArgs ? specificationIndex - specifications.size() + 1 : -1;
-
-            if (typeVarArgsIndex >= 0 && specVarArgsIndex >= 0) {
-                // both specifications and types have a variable number of arguments
-                // we would get into an endless loop if we would continue
-                break;
-            }
-
-            Parameter resolvedParameter = matchParameter(specification, actualType, specVarArgsIndex, typeVarArgsIndex);
-            if (resolvedParameter == null) {
-                return null;
-            }
-            parsedParams.add(resolvedParameter);
-            typeIndex++;
-            specificationIndex++;
-        }
-
-        if (typeIndex < types.size()) {
-            // additional types available
-            if (spec.isIgnoreAdditionalParameters()) {
-                return parsedParams;
-            } else {
-                return null;
-            }
-        }
-
-        return parsedParams;
-    }
-
-    private static ParameterSpec nextSpecification(List<ParameterSpec> specifications, int specIndex, boolean varArgs) {
-        if (varArgs && specIndex >= specifications.size() - 1 && !specifications.isEmpty()) {
-            return specifications.get(specifications.size() - 1);
-        } else if (specIndex < specifications.size()) {
-            return specifications.get(specIndex);
-        } else {
-            return null;
-        }
-    }
-
-    private static TypeMirror nextActualType(List<TypeMirror> types, int typeIndex, boolean varArgs) {
-        if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) {
-            // unpack varargs array argument
-            TypeMirror actualType = types.get(types.size() - 1);
-            if (actualType.getKind() == TypeKind.ARRAY) {
-                actualType = ((ArrayType) actualType).getComponentType();
-            }
-            return actualType;
-        } else if (typeIndex < types.size()) {
-            return types.get(typeIndex);
-        } else {
-            return null;
-        }
-    }
-
-    private Parameter matchParameter(ParameterSpec specification, TypeMirror mirror, int specificationIndex, int varArgsIndex) {
-        TypeMirror resolvedType = mirror;
-        if (hasError(resolvedType)) {
-            return null;
-        }
-
-        if (!specification.matches(resolvedType)) {
-            return null;
-        }
-
-        TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType);
-        if (resolvedTypeData != null) {
-            return new Parameter(specification, resolvedTypeData, specificationIndex, varArgsIndex);
-        } else {
-            return new Parameter(specification, resolvedType, specificationIndex, varArgsIndex);
-        }
-    }
-
-    public final E create(String id, int naturalOrder, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List<TypeMirror> parameterTypes) {
-        return parseImpl(createSpecification(methodMetadata, mirror), naturalOrder, id, methodMetadata, mirror, returnType, parameterTypes);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java	Mon Aug 18 17:44:42 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java	Mon Aug 18 18:41:16 2014 +0200
@@ -35,9 +35,9 @@
 
     public ExecutableTypeMethodParser(ProcessorContext context, NodeData node) {
         super(context, node);
-        setEmitErrors(false);
         setParseNullOnError(false);
-        setUseVarArgs(true);
+        getParser().setEmitErrors(false);
+        getParser().setUseVarArgs(true);
     }
 
     @Override
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java	Mon Aug 18 17:44:42 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java	Mon Aug 18 18:41:16 2014 +0200
@@ -35,14 +35,14 @@
 
 public class GuardParser extends NodeMethodParser<GuardData> {
 
-    private final Set<String> guardNames;
-    private final TemplateMethod compatibleSource;
+    private final GuardExpression expression;
+    private final TemplateMethod guardedMethod;
 
-    public GuardParser(ProcessorContext context, NodeData node, TemplateMethod compatibleSource, Set<String> guardNames) {
+    public GuardParser(ProcessorContext context, NodeData node, TemplateMethod compatibleSource, GuardExpression expression) {
         super(context, node);
-        this.guardNames = guardNames;
-        this.compatibleSource = compatibleSource;
-        setEmitErrors(false);
+        this.expression = expression;
+        this.guardedMethod = compatibleSource;
+        getParser().setEmitErrors(false);
         setParseNullOnError(false);
     }
 
@@ -55,21 +55,35 @@
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
         MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null);
         spec.setIgnoreAdditionalSpecifications(true);
-        if (compatibleSource != null) {
-            spec.getRequired().clear();
-            for (Parameter parameter : compatibleSource.getRequiredParameters()) {
-                List<TypeMirror> typeMirrors = ElementUtils.getAssignableTypes(getContext(), parameter.getType());
-                Set<String> typeIds = new HashSet<>();
-                for (TypeMirror typeMirror : typeMirrors) {
-                    typeIds.add(ElementUtils.getUniqueIdentifier(typeMirror));
+        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));
                 }
-
-                spec.addRequired(new ParameterSpec(parameter.getSpecification(), typeMirrors, typeIds));
+            }
+        } 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));
+        }
+        typeIds.retainAll(getTypeSystem().getTypeIdentifiers());
+
+        return new ParameterSpec(parameter.getSpecification(), typeMirrors, typeIds);
+    }
+
     @Override
     protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
         Set<TypeMirror> typeMirrors = new LinkedHashSet<>();
@@ -90,7 +104,7 @@
 
     @Override
     public boolean isParsable(ExecutableElement method) {
-        return guardNames == null || guardNames.contains(method.getSimpleName().toString());
+        return true;
     }
 
     @Override
@@ -102,7 +116,7 @@
         }
         List<GuardExpression> guardExpressions = new ArrayList<>();
         for (String string : impliesExpressions) {
-            guardExpressions.add(new GuardExpression(string));
+            guardExpressions.add(new GuardExpression(string, false));
         }
         return new GuardData(method, guardExpressions);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java	Mon Aug 18 18:41:16 2014 +0200
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 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 static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public final class MethodSpecParser {
+
+    private boolean emitErrors = true;
+    private boolean useVarArgs = false;
+
+    private final Template template;
+
+    public MethodSpecParser(Template template) {
+        this.template = template;
+    }
+
+    public Template getTemplate() {
+        return template;
+    }
+
+    public TypeSystemData getTypeSystem() {
+        return template.getTypeSystem();
+    }
+
+    public boolean isEmitErrors() {
+        return emitErrors;
+    }
+
+    public boolean isUseVarArgs() {
+        return useVarArgs;
+    }
+
+    public void setEmitErrors(boolean emitErrors) {
+        this.emitErrors = emitErrors;
+    }
+
+    public void setUseVarArgs(boolean useVarArgs) {
+        this.useVarArgs = useVarArgs;
+    }
+
+    public TemplateMethod parse(MethodSpec methodSpecification, ExecutableElement method, AnnotationMirror annotation, int naturalOrder) {
+        if (methodSpecification == null) {
+            return null;
+        }
+
+        methodSpecification.applyTypeDefinitions("types");
+
+        String id = method.getSimpleName().toString();
+        TypeMirror returnType = method.getReturnType();
+        List<TypeMirror> parameterTypes = new ArrayList<>();
+        for (VariableElement var : method.getParameters()) {
+            parameterTypes.add(var.asType());
+        }
+
+        return parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, parameterTypes);
+    }
+
+    public TemplateMethod parseImpl(MethodSpec methodSpecification, int naturalOrder, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType,
+                    List<TypeMirror> parameterTypes) {
+        ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
+        Parameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, -1, -1);
+        if (returnTypeMirror == null) {
+            if (emitErrors) {
+                TemplateMethod invalidMethod = new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<Parameter> emptyList());
+                String expectedReturnType = returnTypeSpec.toSignatureString(true);
+                String actualReturnType = ElementUtils.getSimpleName(returnType);
+
+                String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
+                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
+                invalidMethod.addError(message);
+                return invalidMethod;
+            } else {
+                return null;
+            }
+        }
+
+        List<Parameter> parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method != null ? method.isVarArgs() : false);
+        if (parameters == null) {
+            if (isEmitErrors() && method != null) {
+                TemplateMethod invalidMethod = new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<Parameter> emptyList());
+                String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(method),
+                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
+                invalidMethod.addError(message);
+                return invalidMethod;
+            } else {
+                return null;
+            }
+        }
+
+        return new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, parameters);
+    }
+
+    private static String createActualSignature(ExecutableElement method) {
+        StringBuilder b = new StringBuilder("(");
+        String sep = "";
+        if (method != null) {
+            for (VariableElement var : method.getParameters()) {
+                b.append(sep);
+                b.append(ElementUtils.getSimpleName(var.asType()));
+                sep = ", ";
+            }
+        }
+        b.append(")");
+        return b.toString();
+    }
+
+    /*
+     * Parameter parsing tries to parse required arguments starting from offset 0 with increasing
+     * offset until it finds a signature end that matches the required specification. If there is no
+     * end matching the required arguments, parsing fails. Parameters prior to the parsed required
+     * ones are cut and used to parse the optional parameters.
+     */
+    private List<Parameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes, boolean varArgs) {
+        List<Parameter> parsedRequired = null;
+        int offset = 0;
+        for (; offset <= parameterTypes.size(); offset++) {
+            List<TypeMirror> parameters = new ArrayList<>();
+            parameters.addAll(parameterTypes.subList(offset, parameterTypes.size()));
+            parsedRequired = parseParametersRequired(spec, parameters, varArgs);
+            if (parsedRequired != null) {
+                break;
+            }
+        }
+
+        if (parsedRequired == null) {
+            return null;
+        }
+
+        if (parsedRequired.isEmpty() && offset == 0) {
+            offset = parameterTypes.size();
+        }
+        List<TypeMirror> potentialOptionals = parameterTypes.subList(0, offset);
+        List<Parameter> parsedOptionals = parseParametersOptional(spec, potentialOptionals);
+        if (parsedOptionals == null) {
+            return null;
+        }
+
+        List<Parameter> finalParameters = new ArrayList<>();
+        finalParameters.addAll(parsedOptionals);
+        finalParameters.addAll(parsedRequired);
+        return finalParameters;
+    }
+
+    private List<Parameter> parseParametersOptional(MethodSpec spec, List<TypeMirror> types) {
+        List<Parameter> parsedParams = new ArrayList<>();
+
+        int typeStartIndex = 0;
+        List<ParameterSpec> specifications = spec.getOptional();
+        outer: for (int specIndex = 0; specIndex < specifications.size(); specIndex++) {
+            ParameterSpec specification = specifications.get(specIndex);
+            for (int typeIndex = typeStartIndex; typeIndex < types.size(); typeIndex++) {
+                TypeMirror actualType = types.get(typeIndex);
+                Parameter optionalParam = matchParameter(specification, actualType, -1, -1);
+                if (optionalParam != null) {
+                    parsedParams.add(optionalParam);
+                    typeStartIndex = typeIndex + 1;
+                    continue outer;
+                }
+            }
+        }
+
+        if (typeStartIndex < types.size()) {
+            // not enough types found
+            return null;
+        }
+        return parsedParams;
+    }
+
+    private List<Parameter> parseParametersRequired(MethodSpec spec, List<TypeMirror> types, boolean typeVarArgs) {
+        List<Parameter> parsedParams = new ArrayList<>();
+        List<ParameterSpec> specifications = spec.getRequired();
+        boolean specVarArgs = spec.isVariableRequiredParameters();
+        int typeIndex = 0;
+        int specificationIndex = 0;
+
+        ParameterSpec specification;
+        while ((specification = nextSpecification(specifications, specificationIndex, specVarArgs)) != null) {
+            TypeMirror actualType = nextActualType(types, typeIndex, typeVarArgs);
+            if (actualType == null) {
+                if (spec.isIgnoreAdditionalSpecifications()) {
+                    break;
+                }
+                return null;
+            }
+
+            int typeVarArgsIndex = typeVarArgs ? typeIndex - types.size() + 1 : -1;
+            int specVarArgsIndex = specVarArgs ? specificationIndex - specifications.size() + 1 : -1;
+
+            if (typeVarArgsIndex >= 0 && specVarArgsIndex >= 0) {
+                // both specifications and types have a variable number of arguments
+                // we would get into an endless loop if we would continue
+                break;
+            }
+
+            Parameter resolvedParameter = matchParameter(specification, actualType, specVarArgsIndex, typeVarArgsIndex);
+            if (resolvedParameter == null) {
+                return null;
+            }
+            parsedParams.add(resolvedParameter);
+            typeIndex++;
+            specificationIndex++;
+        }
+
+        if (typeIndex < types.size()) {
+            // additional types available
+            if (spec.isIgnoreAdditionalParameters()) {
+                return parsedParams;
+            } else {
+                return null;
+            }
+        }
+
+        return parsedParams;
+    }
+
+    private static ParameterSpec nextSpecification(List<ParameterSpec> specifications, int specIndex, boolean varArgs) {
+        if (varArgs && specIndex >= specifications.size() - 1 && !specifications.isEmpty()) {
+            return specifications.get(specifications.size() - 1);
+        } else if (specIndex < specifications.size()) {
+            return specifications.get(specIndex);
+        } else {
+            return null;
+        }
+    }
+
+    private static TypeMirror nextActualType(List<TypeMirror> types, int typeIndex, boolean varArgs) {
+        if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) {
+            // unpack varargs array argument
+            TypeMirror actualType = types.get(types.size() - 1);
+            if (actualType.getKind() == TypeKind.ARRAY) {
+                actualType = ((ArrayType) actualType).getComponentType();
+            }
+            return actualType;
+        } else if (typeIndex < types.size()) {
+            return types.get(typeIndex);
+        } else {
+            return null;
+        }
+    }
+
+    private Parameter matchParameter(ParameterSpec specification, TypeMirror mirror, int specificationIndex, int varArgsIndex) {
+        TypeMirror resolvedType = mirror;
+        if (hasError(resolvedType)) {
+            return null;
+        }
+
+        if (!specification.matches(resolvedType)) {
+            return null;
+        }
+
+        TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType);
+        if (resolvedTypeData != null) {
+            return new Parameter(specification, resolvedTypeData, specificationIndex, varArgsIndex);
+        } else {
+            return new Parameter(specification, resolvedType, specificationIndex, varArgsIndex);
+        }
+    }
+
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeExecutionData.java	Mon Aug 18 17:44:42 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 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 javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.model.*;
-import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
-
-public class NodeExecutionData {
-
-    private final NodeChildData child;
-    private final String name;
-    private final int index;
-    private final boolean shortCircuit;
-
-    public NodeExecutionData(NodeChildData child, int index, boolean shortCircuit) {
-        this.child = child;
-        this.index = index;
-        this.shortCircuit = shortCircuit;
-        this.name = createName();
-    }
-
-    private String createName() {
-        if (isIndexed()) {
-            return child.getName() + index;
-        }
-        return child.getName();
-    }
-
-    public TypeMirror getNodeType() {
-        TypeMirror type;
-        if (child.getCardinality() == Cardinality.MANY && child.getNodeType().getKind() == TypeKind.ARRAY) {
-            type = ((ArrayType) child.getNodeType()).getComponentType();
-        } else {
-            type = child.getNodeType();
-        }
-        return type;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public NodeChildData getChild() {
-        return child;
-    }
-
-    public int getIndex() {
-        return index;
-    }
-
-    public boolean isIndexed() {
-        return index > -1;
-    }
-
-    public boolean isShortCircuit() {
-        return shortCircuit;
-    }
-
-    public String getShortCircuitId() {
-        return createShortCircuitId(child, index);
-    }
-
-    public static String createShortCircuitId(NodeChildData child, int varArgsIndex) {
-        String shortCircuitName = child.getName();
-        if (child.getCardinality().isMany()) {
-            shortCircuitName = shortCircuitName + "[" + varArgsIndex + "]";
-        }
-        return shortCircuitName;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Mon Aug 18 17:44:42 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Mon Aug 18 18:41:16 2014 +0200
@@ -190,12 +190,18 @@
                     continue;
                 }
                 TypeElement typeElement = ElementUtils.fromTypeMirror(importGuardClass);
-                if (!typeElement.getModifiers().contains(Modifier.PUBLIC)) {
+
+                // hack to reload type is necessary for incremental compiling in eclipse.
+                // otherwise methods inside of import guard types are just not found.
+                typeElement = ElementUtils.fromTypeMirror(context.reloadType(typeElement.asType()));
+
+                if (typeElement.getEnclosingElement().getKind().isClass() && !typeElement.getModifiers().contains(Modifier.PUBLIC)) {
                     node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' must be public.", ElementUtils.getQualifiedName(importGuardClass));
                     continue;
                 }
 
                 List<? extends ExecutableElement> importMethods = ElementFilter.methodsIn(processingEnv.getElementUtils().getAllMembers(typeElement));
+
                 for (ExecutableElement importMethod : importMethods) {
                     if (!importMethod.getModifiers().contains(Modifier.PUBLIC) || !importMethod.getModifiers().contains(Modifier.STATIC)) {
                         continue;
@@ -883,53 +889,70 @@
     }
 
     private void initializeGuards(List<? extends Element> elements, NodeData node) {
-        Map<String, List<GuardData>> guards = new HashMap<>();
+        Map<String, List<ExecutableElement>> potentialGuards = new HashMap<>();
         for (SpecializationData specialization : node.getSpecializations()) {
             for (GuardExpression exp : specialization.getGuards()) {
-                guards.put(exp.getGuardName(), null);
+                potentialGuards.put(exp.getGuardName(), null);
             }
         }
 
-        GuardParser parser = new GuardParser(context, node, null, guards.keySet());
-        List<GuardData> resolvedGuards = parser.parse(elements);
-        for (GuardData guard : resolvedGuards) {
-            List<GuardData> groupedGuards = guards.get(guard.getMethodName());
-            if (groupedGuards == null) {
-                groupedGuards = new ArrayList<>();
-                guards.put(guard.getMethodName(), groupedGuards);
+        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;
             }
-            groupedGuards.add(guard);
+
+            if (!ElementUtils.typeEquals(potentialGuard.getReturnType(), booleanType)) {
+                continue;
+            }
+
+            List<ExecutableElement> potentialMethods = potentialGuards.get(methodName);
+            if (potentialMethods == null) {
+                potentialMethods = new ArrayList<>();
+                potentialGuards.put(methodName, potentialMethods);
+            }
+            potentialMethods.add(potentialGuard);
         }
 
         for (SpecializationData specialization : node.getSpecializations()) {
             for (GuardExpression exp : specialization.getGuards()) {
-                resolveGuardExpression(node, specialization, guards, exp);
+                resolveGuardExpression(node, specialization, potentialGuards, exp);
             }
         }
     }
 
-    private void resolveGuardExpression(NodeData node, TemplateMethod source, Map<String, List<GuardData>> guards, GuardExpression expression) {
-        List<GuardData> availableGuards = guards.get(expression.getGuardName());
+    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. Please note that all signature types of the method guard must be declared in the type system.", expression.getGuardName());
+            source.addError("No compatible guard with method name '%s' found.", expression.getGuardName());
             return;
         }
-        List<ExecutableElement> guardMethods = new ArrayList<>();
-        for (GuardData guard : availableGuards) {
-            guardMethods.add(guard.getMethod());
+
+        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);
         }
-        GuardParser parser = new GuardParser(context, node, source, null);
-        List<GuardData> matchingGuards = parser.parse(guardMethods);
+
+        GuardParser parser = new GuardParser(context, node, source, expression);
+        List<GuardData> matchingGuards = parser.parse(availableGuards);
         if (!matchingGuards.isEmpty()) {
             GuardData guard = matchingGuards.get(0);
             // use the shared instance of the guard data
-            for (GuardData guardData : availableGuards) {
-                if (guardData.getMethod() == guard.getMethod()) {
-                    expression.setGuard(guardData);
-                    return;
-                }
-            }
-            throw new AssertionError("Should not reach here.");
+            expression.setResolvedGuard(guard);
         } else {
             MethodSpec spec = parser.createSpecification(source.getMethod(), source.getMarkerAnnotation());
             spec.applyTypeDefinitions("types");
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java	Mon Aug 18 17:44:42 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java	Mon Aug 18 18:41:16 2014 +0200
@@ -424,16 +424,15 @@
     }
 
     public boolean isTypeGuardUsedInAnyGuardBelow(ProcessorContext context, SpecializationData source, TypeGuard typeGuard) {
+        NodeExecutionData execution = source.getNode().getChildExecutions().get(typeGuard.getSignatureIndex());
 
         for (GuardExpression guard : guards) {
-            Parameter guardParameter = guard.getResolvedGuard().getSignatureParameter(typeGuard.getSignatureIndex());
-            if (guardParameter == null) {
-                // guardParameters are optional
-                continue;
-            }
+            List<Parameter> guardParameters = guard.getResolvedGuard().findByExecutionData(execution);
             Parameter sourceParameter = source.getSignatureParameter(typeGuard.getSignatureIndex());
-            if (sourceParameter.getTypeSystemType().needsCastTo(guardParameter.getType())) {
-                return true;
+            for (Parameter guardParameter : guardParameters) {
+                if (sourceParameter.getTypeSystemType().needsCastTo(guardParameter.getType())) {
+                    return true;
+                }
             }
         }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java	Mon Aug 18 17:44:42 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java	Mon Aug 18 18:41:16 2014 +0200
@@ -84,7 +84,7 @@
         List<String> guardDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards");
         List<GuardExpression> guardExpressions = new ArrayList<>();
         for (String guardDef : guardDefs) {
-            guardExpressions.add(new GuardExpression(guardDef));
+            guardExpressions.add(new GuardExpression(guardDef, true));
         }
         specialization.setGuards(guardExpressions);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java	Mon Aug 18 18:41:16 2014 +0200
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 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 javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public abstract class TemplateMethodParser<T extends Template, E extends TemplateMethod> {
+
+    protected final T template;
+    private final ProcessorContext context;
+    private final MethodSpecParser parser;
+
+    private boolean parseNullOnError;
+
+    public TemplateMethodParser(ProcessorContext context, T template) {
+        this.template = template;
+        this.context = context;
+        this.parser = new MethodSpecParser(template);
+    }
+
+    public void setParseNullOnError(boolean parseNullOnError) {
+        this.parseNullOnError = parseNullOnError;
+    }
+
+    public boolean isParseNullOnError() {
+        return parseNullOnError;
+    }
+
+    public MethodSpecParser getParser() {
+        return parser;
+    }
+
+    public ProcessorContext getContext() {
+        return context;
+    }
+
+    public TypeSystemData getTypeSystem() {
+        return template.getTypeSystem();
+    }
+
+    public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror);
+
+    public abstract E create(TemplateMethod method, boolean invalid);
+
+    public abstract boolean isParsable(ExecutableElement method);
+
+    public Class<? extends Annotation> getAnnotationType() {
+        return null;
+    }
+
+    public final List<E> parse(List<? extends Element> elements) {
+        List<ExecutableElement> methods = new ArrayList<>();
+        methods.addAll(ElementFilter.methodsIn(elements));
+
+        List<E> parsedMethods = new ArrayList<>();
+        boolean valid = true;
+        int naturalOrder = 0;
+        for (ExecutableElement method : methods) {
+            if (!isParsable(method)) {
+                continue;
+            }
+
+            Class<? extends Annotation> annotationType = getAnnotationType();
+            AnnotationMirror mirror = null;
+            if (annotationType != null) {
+                mirror = ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType);
+            }
+
+            E parsedMethod = parse(naturalOrder, method, mirror);
+
+            if (method.getModifiers().contains(Modifier.PRIVATE) && parser.isEmitErrors()) {
+                parsedMethod.addError("Method annotated with @%s must not be private.", getAnnotationType().getSimpleName());
+                parsedMethods.add(parsedMethod);
+                valid = false;
+                continue;
+            }
+
+            if (parsedMethod != null) {
+                parsedMethods.add(parsedMethod);
+            } else {
+                valid = false;
+            }
+            naturalOrder++;
+        }
+        Collections.sort(parsedMethods);
+
+        if (!valid && isParseNullOnError()) {
+            return null;
+        }
+        return parsedMethods;
+    }
+
+    private E parse(int naturalOrder, ExecutableElement method, AnnotationMirror annotation) {
+        MethodSpec methodSpecification = createSpecification(method, annotation);
+        if (methodSpecification == null) {
+            return null;
+        }
+
+        TemplateMethod templateMethod = parser.parse(methodSpecification, method, annotation, naturalOrder);
+        if (templateMethod != null) {
+            return create(templateMethod, templateMethod.hasErrors());
+        }
+        return null;
+    }
+
+    public final E create(String id, int naturalOrder, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List<TypeMirror> parameterTypes) {
+        TemplateMethod method = parser.parseImpl(createSpecification(methodMetadata, mirror), naturalOrder, id, methodMetadata, mirror, returnType, parameterTypes);
+        if (method != null) {
+            return create(method, method.hasErrors());
+        }
+        return null;
+    }
+}