changeset 13538:b26ce93265d8

Merge.
author Christian Humer <christian.humer@gmail.com>
date Tue, 07 Jan 2014 22:36:23 +0100
parents 93068303f856 (diff) 8602fcb6ceb3 (current diff)
children 504d3d12a939
files
diffstat 41 files changed, 1797 insertions(+), 2036 deletions(-) [+]
line wrap: on
line diff
--- /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/BoxedString.java	Tue Jan 07 22:36:23 2014 +0100
@@ -0,0 +1,41 @@
+/*
+ * 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.api.dsl.test;
+
+public class BoxedString {
+
+    private final String delegate;
+
+    public BoxedString(String delegate) {
+        this.delegate = delegate;
+    }
+
+    public String getDelegate() {
+        return delegate;
+    }
+
+    @Override
+    public String toString() {
+        return getDelegate();
+    }
+}
--- /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/CreateCastTest.java	Tue Jan 07 22:36:23 2014 +0100
@@ -0,0 +1,122 @@
+/*
+ * 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.api.dsl.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.CreateCastTestFactory.CreateCastNode1Factory;
+import com.oracle.truffle.api.dsl.test.CreateCastTestFactory.CreateCastNode2Factory;
+import com.oracle.truffle.api.dsl.test.CreateCastTestFactory.CreateCastNode3Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ChildrenNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.nodes.*;
+
+@SuppressWarnings("unused")
+public class CreateCastTest {
+
+    @Test
+    public void testCastNode1() {
+        TestRootNode<CreateCastNode1> root = TestHelper.createRoot(CreateCastNode1Factory.getInstance());
+        Assert.assertEquals(1, root.getNode().invocations);
+    }
+
+    @Test
+    public void testCastNode2() {
+        TestRootNode<CreateCastNode2> root = TestHelper.createRoot(CreateCastNode2Factory.getInstance());
+        Assert.assertEquals(2, root.getNode().invocations);
+    }
+
+    @Test
+    public void testCastNode3() {
+        TestRootNode<CreateCastNode3> root = TestHelper.createRoot(CreateCastNode3Factory.getInstance());
+        Assert.assertEquals(1, root.getNode().invocations);
+    }
+
+    @NodeChild("a")
+    abstract static class CreateCastNode1 extends ValueNode {
+
+        int invocations = 0;
+
+        @CreateCast({"a"})
+        public ValueNode createCast(ValueNode node) {
+            invocations++;
+            return node;
+        }
+
+        @Specialization
+        public int doInteger(int a) {
+            throw new AssertionError();
+        }
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class CreateCastNode2 extends ValueNode {
+
+        int invocations = 0;
+
+        @CreateCast({"a", "b"})
+        public ValueNode createCast(ValueNode node) {
+            invocations++;
+            return node;
+        }
+
+        @Specialization
+        public int doInteger(int a, int b) {
+            throw new AssertionError();
+        }
+    }
+
+    abstract static class CreateCastNode3 extends ChildrenNode {
+
+        int invocations = 0;
+
+        @CreateCast("children")
+        public ValueNode[] createCast(ValueNode[] node) {
+            invocations++;
+            return node;
+        }
+
+        @Specialization
+        public int doInteger(int a) {
+            throw new AssertionError();
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class CreateCastFailNode1 extends ValueNode {
+
+        @ExpectError({"Specified child '' not found."})
+        @CreateCast({""})
+        public ValueNode createCast(Node child) {
+            throw new AssertionError();
+        }
+
+        @Specialization
+        public int doInteger(int a) {
+            throw new AssertionError();
+        }
+    }
+
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java	Tue Jan 07 22:36:23 2014 +0100
@@ -38,8 +38,6 @@
 import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve1Factory;
 import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve2Factory;
 import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve3Factory;
-import com.oracle.truffle.api.dsl.test.NodeContainerTest.Str;
-import com.oracle.truffle.api.dsl.test.NodeContainerTest.StrBase;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.Abstract;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.BExtendsAbstract;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.CExtendsAbstract;
@@ -124,18 +122,18 @@
     public void testGuardWithBaseClass() {
         TestRootNode<?> root = createRoot(GuardWithBaseClassFactory.getInstance());
 
-        assertEquals(42, executeWith(root, new Str("42")));
+        assertEquals(42, executeWith(root, new BExtendsAbstract()));
     }
 
     @NodeChild("expression")
     public abstract static class GuardWithBaseClass extends ValueNode {
 
-        boolean baseGuard(StrBase base) {
+        boolean baseGuard(Abstract base) {
             return true;
         }
 
         @Specialization(guards = "baseGuard")
-        int doSpecialized(Str value0) {
+        int doSpecialized(BExtendsAbstract value0) {
             return 42;
         }
     }
@@ -227,7 +225,7 @@
     @Test
     public void testGuardResolve2() {
         TestRootNode<?> root = createRoot(TestGuardResolve2Factory.getInstance());
-        assertEquals(42, executeWith(root, new Str("")));
+        assertEquals(42, executeWith(root, new BExtendsAbstract()));
     }
 
     @NodeChild("expression")
@@ -237,12 +235,12 @@
             return false;
         }
 
-        boolean guard(StrBase primitive) {
+        boolean guard(Abstract primitive) {
             return true;
         }
 
         @Specialization(guards = "guard")
-        int doSpecialized(Str value0) {
+        int doSpecialized(BExtendsAbstract value0) {
             return 42;
         }
     }
@@ -251,7 +249,7 @@
     public void testGuardResolve3() {
         TestRootNode<?> root = createRoot(TestGuardResolve3Factory.getInstance());
 
-        assertEquals(42, executeWith(root, new Str("")));
+        assertEquals(42, executeWith(root, new BExtendsAbstract()));
     }
 
     @NodeChild("expression")
@@ -261,16 +259,16 @@
             return false;
         }
 
-        boolean guard(StrBase primitive) {
+        boolean guard(Abstract primitive) {
             return false;
         }
 
-        boolean guard(Str primitive) {
+        boolean guard(BExtendsAbstract primitive) {
             return true;
         }
 
         @Specialization(guards = "guard")
-        int doSpecialized(Str value0) {
+        int doSpecialized(BExtendsAbstract value0) {
             return 42;
         }
     }
@@ -278,12 +276,12 @@
     @NodeChild("expression")
     public abstract static class TestGuardResolve4 extends ValueNode {
 
-        boolean guard(StrBase primitive) {
+        boolean guard(Abstract primitive) {
             return false;
         }
 
         @Specialization(guards = "guard")
-        int doSpecialized(Str value0) {
+        int doSpecialized(BExtendsAbstract value0) {
             return 42;
         }
     }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java	Tue Jan 07 22:36:23 2014 +0100
@@ -28,14 +28,13 @@
 import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast0NodeFactory;
 import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast1NodeFactory;
 import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast2NodeFactory;
-import com.oracle.truffle.api.dsl.test.NodeContainerTest.Str;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
 import com.oracle.truffle.api.frame.*;
 
 public class ImplicitCastTest {
 
-    @TypeSystem({int.class, boolean.class, String.class, Str.class})
+    @TypeSystem({int.class, boolean.class, String.class})
     static class ImplicitCast0Types {
 
         @ImplicitCast
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeContainerTest.java	Tue Jan 07 21:52:07 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +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.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.NodeContainerTestFactory.StrFactory.StrAccessContextFactory;
-import com.oracle.truffle.api.dsl.test.NodeContainerTestFactory.StrFactory.StrConcatFactory;
-import com.oracle.truffle.api.dsl.test.NodeContainerTestFactory.StrFactory.StrLengthFactory;
-import com.oracle.truffle.api.dsl.test.NodeContainerTestFactory.StrFactory.StrSubstrFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class NodeContainerTest {
-
-    @Test
-    public void testConcat() {
-        TestRootNode<BuiltinNode> node = createRoot(StrConcatFactory.getInstance(), new Context());
-        Str str1 = new Str("42");
-        Str str2 = new Str(" is the number.");
-        assertEquals(str1.concat(str2), executeWith(node, str1, str2));
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testConcatUnsupported() {
-        TestRootNode<BuiltinNode> node = createRoot(StrConcatFactory.getInstance(), new Context());
-        executeWith(node, 42, new Str(" is the number."));
-    }
-
-    @Test
-    public void testSubstrSpecialized() {
-        TestRootNode<BuiltinNode> node = createRoot(StrSubstrFactory.getInstance(), new Context());
-        Str str = new Str("test 42");
-
-        assertEquals(str.substr(5, 7), executeWith(node, str, 5, 7));
-    }
-
-    @Test
-    public void testSubstrGeneric() {
-        TestRootNode<BuiltinNode> node = createRoot(StrSubstrFactory.getInstance(), new Context());
-        Str str = new Str("test 42");
-
-        assertEquals(Str.substr(str, "5", "7"), executeWith(node, str, "5", "7"));
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testSubstrUnsupported() {
-        TestRootNode<BuiltinNode> node = createRoot(StrSubstrFactory.getInstance(), new Context());
-        executeWith(node, new Object(), "5", "7");
-    }
-
-    @Test
-    public void testLength() {
-        TestRootNode<BuiltinNode> node = createRoot(StrLengthFactory.getInstance(), new Context());
-        Str testStr = new Str("test 42");
-        assertEquals(testStr.length(), executeWith(node, testStr));
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testLengthUnsupported() {
-        TestRootNode<BuiltinNode> node = createRoot(StrLengthFactory.getInstance(), new Context());
-        executeWith(node, new Object());
-    }
-
-    @Test
-    public void testAccessContext() {
-        Context context = new Context();
-        TestRootNode<BuiltinNode> node = createRoot(StrAccessContextFactory.getInstance(), context);
-        // accessible by node
-        assertSame(context, node.getNode().getContext());
-        // accessible by execution
-        assertSame(context, executeWith(node));
-    }
-
-    static class StrBase {
-
-    }
-
-    @NodeContainer(BuiltinNode.class)
-    static class Str extends StrBase {
-
-        private final String internal;
-
-        public Str(String internal) {
-            this.internal = internal;
-        }
-
-        @Specialization
-        Str concat(Str s1) {
-            return new Str(internal + s1.internal);
-        }
-
-        @Specialization
-        Str substr(int beginIndex, int endIndex) {
-            return new Str(internal.substring(beginIndex, endIndex));
-        }
-
-        @Generic
-        static Str substr(Object thisValue, Object beginIndex, Object endIndex) {
-            if (!(thisValue instanceof Str)) {
-                throw new UnsupportedOperationException();
-            }
-            return ((Str) thisValue).substr(convertInt(beginIndex), convertInt(endIndex));
-        }
-
-        @Specialization
-        int length() {
-            return internal.length();
-        }
-
-        @Specialization
-        static Object accessContext(Context context) {
-            return context;
-        }
-
-        static int convertInt(Object value) {
-            if (value instanceof Number) {
-                return ((Number) value).intValue();
-            } else if (value instanceof String) {
-                return Integer.parseInt((String) value);
-            }
-            throw new RuntimeException("Invalid datatype");
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof Str) {
-                return internal.equals(((Str) obj).internal);
-            }
-            return super.equals(obj);
-        }
-
-        @Override
-        public String toString() {
-            return internal;
-        }
-
-        @Override
-        public int hashCode() {
-            return internal.hashCode();
-        }
-    }
-
-    @NodeChild(value = "children", type = ValueNode[].class)
-    @NodeField(name = "context", type = Context.class)
-    abstract static class BuiltinNode extends ValueNode {
-
-        public abstract Context getContext();
-    }
-
-    static class Context {
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java	Tue Jan 07 22:36:23 2014 +0100
@@ -28,8 +28,13 @@
 import org.junit.*;
 
 import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.*;
-import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.TestContainerFactory.TestContainerContainerFieldFactory;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldNoGetterTestNodeFactory;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldTestNodeFactory;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.MultipleFieldsTestNodeFactory;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.ObjectContainerNodeFactory;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.RewriteTestNodeFactory;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.StringFieldTestNodeFactory;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.TestContainerFactory;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
 
 public class NodeFieldTest {
@@ -125,7 +130,7 @@
 
     @Test
     public void testStringContainer() {
-        assertEquals(42, createCallTarget(TestContainerContainerFieldFactory.create(42, "42")).call());
+        assertEquals(42, createCallTarget(TestContainerFactory.create("42")).call());
     }
 
     @NodeField(name = "field", type = int.class)
@@ -135,13 +140,12 @@
 
     }
 
-    @NodeContainer(IntContainerNode.class)
     @NodeField(name = "anotherField", type = String.class)
-    abstract static class TestContainer {
+    abstract static class TestContainer extends ValueNode {
 
         @Specialization
-        static int containerField(int field, String anotherField) {
-            return anotherField.equals("42") ? field : -1;
+        int containerField(String field) {
+            return field.equals("42") ? 42 : -1;
         }
 
     }
--- /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/ShortCircuitTest.java	Tue Jan 07 22:36:23 2014 +0100
@@ -0,0 +1,144 @@
+/*
+ * 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.api.dsl.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.DoubleChildNodeFactory;
+import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.SingleChildNodeFactory;
+import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.VarArgsNodeFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestArguments;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class ShortCircuitTest {
+
+    @Test
+    public void testSingleChild1() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        CallTarget callTarget = TestHelper.createCallTarget(SingleChildNodeFactory.create(arg0));
+        SingleChildNode.needsChild = true;
+        assertEquals(42, callTarget.call(new TestArguments(42)));
+        assertEquals(1, arg0.getInvocationCount());
+    }
+
+    @Test
+    public void testSingleChild2() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        CallTarget callTarget = TestHelper.createCallTarget(SingleChildNodeFactory.create(arg0));
+        SingleChildNode.needsChild = false;
+        assertEquals(0, callTarget.call(new TestArguments(42)));
+        assertEquals(0, arg0.getInvocationCount());
+    }
+
+    @NodeChild("child0")
+    abstract static class SingleChildNode extends ValueNode {
+
+        static boolean needsChild;
+
+        @ShortCircuit("child0")
+        boolean needsChild0() {
+            return needsChild;
+        }
+
+        @Specialization
+        int doIt(boolean hasChild0, int child0) {
+            assert hasChild0 == needsChild0();
+            return child0;
+        }
+
+    }
+
+    @Test
+    public void testDoubleChild1() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(DoubleChildNodeFactory.create(arg0, arg1));
+        assertEquals(42, callTarget.call(new TestArguments(41, 42)));
+        assertEquals(1, arg1.getInvocationCount());
+    }
+
+    @Test
+    public void testDoubleChild2() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(DoubleChildNodeFactory.create(arg0, arg1));
+        assertEquals(0, callTarget.call(new TestArguments(42, 42)));
+        assertEquals(0, arg1.getInvocationCount());
+    }
+
+    @NodeChildren({@NodeChild("child0"), @NodeChild("child1")})
+    @SuppressWarnings("unused")
+    abstract static class DoubleChildNode extends ValueNode {
+
+        @ShortCircuit("child1")
+        boolean needsChild1(Object leftValue) {
+            return leftValue.equals(41);
+        }
+
+        @Specialization
+        int doIt(int child0, boolean hasChild1, int child1) {
+            return child1;
+        }
+
+    }
+
+    @Test
+    public void testVarArgs1() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(VarArgsNodeFactory.create(new ValueNode[]{arg0, arg1}));
+        assertEquals(42, callTarget.call(new TestArguments(41, 42)));
+        assertEquals(1, arg1.getInvocationCount());
+    }
+
+    @Test
+    public void testVarArgs2() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(VarArgsNodeFactory.create(new ValueNode[]{arg0, arg1}));
+        assertEquals(0, callTarget.call(new TestArguments(42, 42)));
+        assertEquals(0, arg1.getInvocationCount());
+    }
+
+    @NodeChild(value = "children", type = ValueNode[].class)
+    abstract static class VarArgsNode extends ValueNode {
+
+        @ShortCircuit("children[1]")
+        boolean needsChild1(Object leftValue) {
+            return leftValue.equals(41);
+        }
+
+        @Specialization
+        @SuppressWarnings("unused")
+        int doIt(int child0, boolean hasChild1, int child1) {
+            return child1;
+        }
+
+    }
+
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java	Tue Jan 07 22:36:23 2014 +0100
@@ -28,7 +28,6 @@
 
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.NodeContainerTest.BuiltinNode;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ChildrenNode;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestArguments;
@@ -52,7 +51,7 @@
         ArgumentNode[] argumentNodes = arguments(factory.getExecutionSignature().size());
 
         List<Object> argumentList = new ArrayList<>();
-        if (ChildrenNode.class.isAssignableFrom(factory.getNodeClass()) || BuiltinNode.class.isAssignableFrom(factory.getNodeClass())) {
+        if (ChildrenNode.class.isAssignableFrom(factory.getNodeClass())) {
             argumentList.add(argumentNodes);
         } else {
             argumentList.addAll(Arrays.asList(argumentNodes));
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Tue Jan 07 22:36:23 2014 +0100
@@ -24,13 +24,12 @@
 
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.NodeContainerTest.Str;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 
 public class TypeSystemTest {
 
-    @TypeSystem({int.class, boolean.class, String.class, Str.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class, Abstract.class, Object[].class})
+    @TypeSystem({int.class, boolean.class, String.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class, Abstract.class, Object[].class})
     static class SimpleTypes {
 
         static int intCheck;
@@ -48,11 +47,6 @@
             return (int) value;
         }
 
-        @ImplicitCast
-        Str castStr(String strvalue) {
-            return new Str(strvalue);
-        }
-
     }
 
     @TypeSystemReference(SimpleTypes.class)
@@ -66,10 +60,6 @@
             return SimpleTypesGen.SIMPLETYPES.expectInteger(execute(frame));
         }
 
-        public Str executeStr(VirtualFrame frame) throws UnexpectedResultException {
-            return SimpleTypesGen.SIMPLETYPES.expectStr(execute(frame));
-        }
-
         public String executeString(VirtualFrame frame) throws UnexpectedResultException {
             return SimpleTypesGen.SIMPLETYPES.expectString(execute(frame));
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/package-info.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/package-info.java	Tue Jan 07 22:36:23 2014 +0100
@@ -41,7 +41,6 @@
  *
  * <ul>
  * <li>What do I need to get started? {@link com.oracle.truffle.api.dsl.test.TypeSystemTest}</li>
- * <li>How would you generate function nodes for runtime objects? {@link com.oracle.truffle.api.dsl.test.NodeContainerTest}</li>
  * </ul>
  * </p>
  *
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeContainer.java	Tue Jan 07 21:52:07 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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;
-
-import java.lang.annotation.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * A node container can be used to enable Truffle-DSL in classes which do not extend {@link Node}.
- * Compared to normal {@link Node} implementation the nodes are not identified by a class but by
- * their method name. There are cases were method signatures are matching exactly but should be in
- * the same {@link Node}. In this case use {@link NodeId} to disambiguate such cases.
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE})
-public @interface NodeContainer {
-
-    /** The node class to use as base class for {@link Node} definitions grouped by method names. */
-    Class<? extends Node> value();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeId.java	Tue Jan 07 21:52:07 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD, ElementType.TYPE})
-public @interface NodeId {
-
-    String value();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/SpecializationListener.java	Tue Jan 07 21:52:07 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD})
-public @interface SpecializationListener {
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java	Tue Jan 07 22:36:23 2014 +0100
@@ -46,17 +46,23 @@
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
         List<String> childNames = Utils.getAnnotationValueList(String.class, mirror, "value");
-        TypeMirror baseType = getContext().getTruffleTypes().getNode();
+        NodeChildData foundChild = null;
         for (String childName : childNames) {
-            NodeChildData child = getNode().findChild(childName);
-            if (child != null) {
-                baseType = child.getOriginalType();
+            foundChild = getNode().findChild(childName);
+            if (foundChild != null) {
                 break;
             }
         }
+        TypeMirror baseType = getContext().getTruffleTypes().getNode();
+        if (foundChild != null) {
+            baseType = foundChild.getOriginalType();
+        }
+
         MethodSpec spec = new MethodSpec(new InheritsParameterSpec(getContext(), "child", baseType));
         addDefaultFieldMethodSpec(spec);
-        spec.addRequired(new ParameterSpec("castedChild", baseType)).setSignature(true);
+        ParameterSpec childSpec = new ParameterSpec("castedChild", baseType);
+        childSpec.setSignature(true);
+        spec.addRequired(childSpec);
         return spec;
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java	Tue Jan 07 22:36:23 2014 +0100
@@ -29,7 +29,6 @@
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
 import com.oracle.truffle.dsl.processor.template.*;
 import com.oracle.truffle.dsl.processor.typesystem.*;
 
@@ -52,13 +51,13 @@
         for (ParameterSpec originalSpec : requiredSpecs) {
             spec.addRequired(new ParameterSpec(originalSpec, allowedTypes));
         }
-
-        spec.setVariableRequiredArguments(true);
-        ParameterSpec other = new ParameterSpec("other", allowedTypes);
-        other.setCardinality(Cardinality.MANY);
-        other.setSignature(true);
-        other.setIndexed(true);
-        spec.addRequired(other);
+        spec.setIgnoreAdditionalSpecifications(true);
+        spec.setIgnoreAdditionalParameters(true);
+        spec.setVariableRequiredParameters(true);
+        // varargs
+        ParameterSpec otherParameters = new ParameterSpec("other", allowedTypes);
+        otherParameters.setSignature(true);
+        spec.addRequired(otherParameters);
         return spec;
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java	Tue Jan 07 22:36:23 2014 +0100
@@ -30,6 +30,7 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.node.SpecializationData.SpecializationKind;
 import com.oracle.truffle.dsl.processor.template.*;
 
 public class GenericParser extends NodeMethodParser<SpecializationData> {
@@ -44,26 +45,20 @@
     }
 
     @Override
-    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, int evaluatedCount) {
-        List<ExecutableTypeData> execTypes = nodeData.findGenericExecutableTypes(getContext(), evaluatedCount);
+    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
+        List<ExecutableTypeData> execTypes = execution.getChild().findGenericExecutableTypes(getContext());
         List<TypeMirror> types = new ArrayList<>();
         for (ExecutableTypeData type : execTypes) {
             types.add(type.getType().getPrimitiveType());
         }
-        ParameterSpec spec = new ParameterSpec(valueName, types);
-        spec.setSignature(true);
+        ParameterSpec spec = new ParameterSpec(execution.getName(), types);
+        spec.setExecution(execution);
         return spec;
     }
 
     @Override
-    protected ParameterSpec createReturnParameterSpec() {
-        return super.createValueParameterSpec("returnValue", getNode(), 0);
-    }
-
-    @Override
     public SpecializationData create(TemplateMethod method, boolean invalid) {
-        SpecializationData data = new SpecializationData(method, true, false, false);
-        return data;
+        return new SpecializationData(getNode(), method, SpecializationKind.GENERIC);
     }
 
     @Override
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java	Tue Jan 07 22:36:23 2014 +0100
@@ -45,29 +45,20 @@
         }
     }
 
-    public enum ExecutionKind {
-        DEFAULT, SHORT_CIRCUIT
-    }
-
-    private final NodeData parent;
+    private NodeData parentNode;
     private final Element sourceElement;
     private final AnnotationMirror sourceAnnotationMirror;
-
     private final String name;
     private final TypeMirror type;
     private final TypeMirror originalType;
     private final Element accessElement;
-
     private final Cardinality cardinality;
-    private final ExecutionKind executionKind;
 
     private List<NodeChildData> executeWith = Collections.emptyList();
 
-    private NodeData nodeData;
+    private NodeData childNode;
 
-    public NodeChildData(NodeData parent, Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement,
-                    Cardinality cardinality, ExecutionKind executionKind) {
-        this.parent = parent;
+    public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality) {
         this.sourceElement = sourceElement;
         this.sourceAnnotationMirror = sourceMirror;
         this.name = name;
@@ -75,7 +66,10 @@
         this.originalType = originalNodeType;
         this.accessElement = accessElement;
         this.cardinality = cardinality;
-        this.executionKind = executionKind;
+    }
+
+    void setParentNode(NodeData parentNode) {
+        this.parentNode = parentNode;
     }
 
     public List<NodeChildData> getExecuteWith() {
@@ -87,23 +81,17 @@
     }
 
     public boolean needsImplicitCast(ProcessorContext context) {
-        if (!parent.needsRewrites(context)) {
+        if (!parentNode.needsRewrites(context)) {
             return false;
         }
 
         boolean used = false;
-        SpecializationData generic = parent.getGenericSpecialization();
-        for (ActualParameter param : generic.getParameters()) {
-            if (!param.getSpecification().isSignature()) {
-                continue;
-            }
-            NodeChildData child = parent.findChild(param.getSpecification().getName());
-            if (child == this) {
+        for (NodeExecutionData execution : parentNode.getChildExecutions()) {
+            if (execution.getChild() == this) {
                 used = true;
                 break;
             }
         }
-
         if (!used) {
             return false;
         }
@@ -112,7 +100,7 @@
     }
 
     public ExecutableTypeData findExecutableType(ProcessorContext context, TypeData targetType) {
-        ExecutableTypeData executableType = nodeData.findExecutableType(targetType, getExecuteWith().size());
+        ExecutableTypeData executableType = childNode.findExecutableType(targetType, getExecuteWith().size());
         if (executableType == null) {
             executableType = findAnyGenericExecutableType(context);
         }
@@ -120,15 +108,15 @@
     }
 
     public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context) {
-        return nodeData.findGenericExecutableTypes(context, getExecuteWith().size());
+        return childNode.findGenericExecutableTypes(context, getExecuteWith().size());
     }
 
     public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) {
-        return nodeData.findAnyGenericExecutableType(context, getExecuteWith().size());
+        return childNode.findAnyGenericExecutableType(context, getExecuteWith().size());
     }
 
     public List<ExecutableTypeData> findExecutableTypes() {
-        return nodeData.getExecutableTypes(getExecuteWith().size());
+        return childNode.getExecutableTypes(getExecuteWith().size());
     }
 
     public TypeMirror getOriginalType() {
@@ -145,12 +133,8 @@
         return sourceAnnotationMirror;
     }
 
-    public boolean isShortCircuit() {
-        return executionKind == ExecutionKind.SHORT_CIRCUIT;
-    }
-
     void setNode(NodeData nodeData) {
-        this.nodeData = nodeData;
+        this.childNode = nodeData;
         if (nodeData != null) {
             getMessages().addAll(nodeData.collectMessages());
         }
@@ -168,12 +152,8 @@
         return cardinality;
     }
 
-    public ExecutionKind getExecutionKind() {
-        return executionKind;
-    }
-
     public NodeData getNodeData() {
-        return nodeData;
+        return childNode;
     }
 
     public String getName() {
@@ -182,7 +162,7 @@
 
     @Override
     public String toString() {
-        return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", execution=" + executionKind + ", node=" + getNodeData() + "]";
+        return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", node=" + getNodeData() + "]";
     }
 
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Tue Jan 07 22:36:23 2014 +0100
@@ -37,7 +37,6 @@
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.ast.*;
 import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind;
 import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard;
 import com.oracle.truffle.dsl.processor.template.*;
 import com.oracle.truffle.dsl.processor.typesystem.*;
@@ -48,6 +47,7 @@
 
     private static final String EXECUTE_GENERIC_NAME = "executeGeneric0";
     private static final String EXECUTE_SPECIALIZE_NAME = "executeAndSpecialize0";
+    private static final String EXECUTE_POLYMORPHIC_NAME = "executePolymorphic0";
 
     private static final String UPDATE_TYPES_NAME = "updateTypes";
 
@@ -71,16 +71,8 @@
         return name;
     }
 
-    private static String nodePolymorphicClassName(NodeData node, SpecializationData specialization) {
-        String nodeid = resolveNodeId(node);
-
-        String name = Utils.firstLetterUpperCase(nodeid);
-        if (specialization == node.getGenericPolymorphicSpecialization()) {
-            name += "PolymorphicNode";
-        } else {
-            name += "Polymorphic" + polymorphicIndex(node, specialization) + "Node";
-        }
-        return name;
+    private static String nodePolymorphicClassName(NodeData node) {
+        return Utils.firstLetterUpperCase(resolveNodeId(node)) + "PolymorphicNode";
     }
 
     private static String resolveNodeId(NodeData node) {
@@ -111,30 +103,6 @@
         return valueName(parameter) + "Cast";
     }
 
-    private static String executeCachedName(SpecializationData polymorphic) {
-        NodeData node = polymorphic.getNode();
-        boolean generic = polymorphic == node.getGenericPolymorphicSpecialization();
-
-        if (generic) {
-            return "executeCachedGeneric0";
-        } else {
-            return "executeCached" + polymorphicIndex(node, polymorphic);
-        }
-    }
-
-    private static int polymorphicIndex(NodeData node, SpecializationData polymorphic) {
-        int index = 0;
-        for (SpecializationData specialization : node.getPolymorphicSpecializations()) {
-            if (specialization == polymorphic) {
-                break;
-            }
-            if (specialization != node.getGenericPolymorphicSpecialization()) {
-                index++;
-            }
-        }
-        return index;
-    }
-
     private void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean evaluated) {
         if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
             method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
@@ -157,7 +125,7 @@
         }
     }
 
-    private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeImplicit,
+    private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame,
                     Map<String, String> customNames) {
         if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
             builder.string("frameValue");
@@ -168,9 +136,6 @@
                 continue;
             }
 
-            if (!includeImplicit && (parameter.isImplicit())) {
-                continue;
-            }
             if (parameter.getSpecification().isLocal()) {
                 continue;
             }
@@ -272,11 +237,6 @@
                 valueParameter = targetParameter;
             }
             TypeMirror targetType = targetParameter.getType();
-
-            if (targetParameter.isImplicit() || valueParameter.isImplicit()) {
-                continue;
-            }
-
             TypeMirror valueType = null;
             if (valueParameter != null) {
                 valueType = valueParameter.getType();
@@ -374,7 +334,7 @@
         builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class));
         builder.startCall("createInfo0");
         builder.doubleQuote("Unsupported values");
-        addInternalValueParameterNames(builder, current, current, null, false, true, null);
+        addInternalValueParameterNames(builder, current, current, null, false, null);
         builder.end().end().end();
     }
 
@@ -440,11 +400,9 @@
         getElement().getEnclosedElements().clear();
 
         Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>();
-        if (node.getDeclaredNodes() != null && !node.getDeclaredNodes().isEmpty()) {
-            for (NodeData nodeChild : node.getDeclaredNodes()) {
-                NodeCodeGenerator generator = new NodeCodeGenerator(getContext());
-                childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements());
-            }
+        for (NodeData nodeChild : node.getEnclosingNodes()) {
+            NodeCodeGenerator generator = new NodeCodeGenerator(getContext());
+            childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements());
         }
 
         if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) {
@@ -526,15 +484,18 @@
 
                 createFactoryMethods(node, clazz, createVisibility);
 
-                if (node.isPolymorphic()) {
-                    PolymorphicNodeFactory generic = new PolymorphicNodeFactory(getContext(), generatedNode);
-                    add(generic, node.getGenericPolymorphicSpecialization());
-                    polymorphicNode = generic.getElement();
-                }
                 for (SpecializationData specialization : node.getSpecializations()) {
                     if (!specialization.isReachable()) {
                         continue;
                     }
+
+                    if (specialization.isPolymorphic() && node.isPolymorphic()) {
+                        PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(getContext(), generatedNode);
+                        add(polymorphicFactory, specialization);
+                        polymorphicNode = polymorphicFactory.getElement();
+                        continue;
+                    }
+
                     add(new SpecializedNodeFactory(context, generatedNode), specialization);
                 }
 
@@ -573,7 +534,7 @@
             }
 
             List<NodeData> children = node.getNodeDeclaringChildren();
-            if (node.getParent() == null && children.size() > 0) {
+            if (node.getDeclaringNode() == null && children.size() > 0) {
                 clazz.add(createGetFactories(node));
             }
 
@@ -632,21 +593,9 @@
             List<TypeMirror> signatureTypes = new ArrayList<>();
             assert !node.getSpecializations().isEmpty();
             SpecializationData data = node.getSpecializations().get(0);
-            for (ActualParameter parameter : data.getParameters()) {
-                ParameterSpec spec = parameter.getSpecification();
-                NodeChildData field = node.findChild(spec.getName());
-                if (field == null) {
-                    continue;
-                }
-
-                TypeMirror type;
-                if (field.getCardinality() == Cardinality.MANY && field.getNodeType().getKind() == TypeKind.ARRAY) {
-                    type = ((ArrayType) field.getNodeType()).getComponentType();
-                } else {
-                    type = field.getNodeType();
-                }
-
-                signatureTypes.add(type);
+
+            for (ActualParameter parameter : data.getSignatureParameters()) {
+                signatureTypes.add(parameter.getSpecification().getExecution().getNodeType());
             }
 
             builder.startReturn().tree(createAsList(builder, signatureTypes, classType)).end();
@@ -768,7 +717,7 @@
         }
 
         private String instanceVarName(NodeData node) {
-            if (node.getParent() != null) {
+            if (node.getDeclaringNode() != null) {
                 return Utils.firstLetterLowerCase(factoryClassName(node)) + "Instance";
             } else {
                 return "instance";
@@ -821,9 +770,9 @@
                 builder.startGroup();
                 NodeData childNode = child;
                 List<NodeData> factories = new ArrayList<>();
-                while (childNode.getParent() != null) {
+                while (childNode.getDeclaringNode() != null) {
                     factories.add(childNode);
-                    childNode = childNode.getParent();
+                    childNode = childNode.getDeclaringNode();
                 }
                 Collections.reverse(factories);
                 for (NodeData nodeData : factories) {
@@ -963,7 +912,7 @@
                     builder.statement("this.next0 = adoptChild(next0)");
                     clazz.add(setter);
 
-                    CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getGenericPolymorphicSpecialization());
+                    CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization());
                     clazz.add(genericCachedExecute);
 
                     getElement().add(createUpdateTypes(clazz.asType()));
@@ -1014,20 +963,17 @@
             CodeTreeBuilder oldBuilder = builder.create();
             CodeTreeBuilder resetBuilder = builder.create();
 
-            for (ActualParameter param : getModel().getParameters()) {
-                if (!param.getSpecification().isSignature()) {
-                    continue;
-                }
-                NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
+            for (ActualParameter param : getModel().getSignatureParameters()) {
+                NodeExecutionData execution = param.getSpecification().getExecution();
 
                 CodeTreeBuilder access = builder.create();
-                access.string("this.").string(child.getName());
-                if (child.getCardinality().isMany()) {
-                    access.string("[").string(String.valueOf(param.getSpecificationIndex())).string("]");
+                access.string("this.").string(execution.getChild().getName());
+                if (execution.isIndexed()) {
+                    access.string("[").string(String.valueOf(execution.getIndex())).string("]");
                 }
 
                 String oldName = "old" + Utils.firstLetterUpperCase(param.getLocalName());
-                oldBuilder.declaration(child.getNodeData().getNodeType(), oldName, access);
+                oldBuilder.declaration(execution.getChild().getNodeData().getNodeType(), oldName, access);
                 nullBuilder.startStatement().tree(access.getRoot()).string(" = null").end();
                 resetBuilder.startStatement().tree(access.getRoot()).string(" = ").string(oldName).end();
             }
@@ -1117,11 +1063,7 @@
             builder.startStatement().startCall("builder", "append").doubleQuote(" (").end().end();
 
             String sep = null;
-            for (ActualParameter parameter : node.getGenericSpecialization().getParameters()) {
-                if (!parameter.getSpecification().isSignature()) {
-                    continue;
-                }
-
+            for (ActualParameter parameter : node.getGenericSpecialization().getSignatureParameters()) {
                 builder.startStatement();
                 builder.string("builder");
                 if (sep != null) {
@@ -1164,13 +1106,12 @@
         }
 
         private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) {
-            String name = executeCachedName(polymorph);
-            CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), name);
-            addInternalValueParameters(cachedExecute, polymorph, true, true);
+            CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_POLYMORPHIC_NAME);
+            addInternalValueParameters(cachedExecute, polymorph, true, false);
 
             ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0);
             boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext());
-            if (sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) {
+            if (sourceThrowsUnexpected && sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) {
                 sourceThrowsUnexpected = false;
             }
             if (sourceThrowsUnexpected) {
@@ -1210,15 +1151,6 @@
                 }
             }
 
-            for (VariableElement var : type.getFields()) {
-                NodeChildData child = node.findChild(var.getSimpleName().toString());
-                if (child != null) {
-                    method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName()));
-                } else {
-                    method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
-                }
-            }
-
             if (superConstructor != null) {
                 builder.startStatement().startSuperCall();
                 for (VariableElement param : superConstructor.getParameters()) {
@@ -1228,11 +1160,17 @@
             }
 
             for (VariableElement var : type.getFields()) {
+                NodeChildData child = node.findChild(var.getSimpleName().toString());
+
+                if (child != null) {
+                    method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName()));
+                } else {
+                    method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
+                }
+
                 builder.startStatement();
                 String fieldName = var.getSimpleName().toString();
 
-                NodeChildData child = node.findChild(fieldName);
-
                 CodeTree init = createStaticCast(builder, child, fieldName);
                 init = createAdoptChild(builder, var.asType(), init);
 
@@ -1327,8 +1265,6 @@
             builder.startStaticCall(getContext().getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end();
             builder.end();
 
-            emitSpecializationListeners(builder, node);
-
             String currentNode = "this";
             for (SpecializationData specialization : node.getSpecializations()) {
                 if (!specialization.getExceptions().isEmpty()) {
@@ -1339,7 +1275,7 @@
             }
 
             builder.startStatement().string("String message = ").startCall("createInfo0").string("reason");
-            addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, true, null);
+            addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, null);
             builder.end().end();
 
             final String currentNodeVar = currentNode;
@@ -1352,7 +1288,7 @@
 
             boolean firstUnreachable = true;
             for (SpecializationData current : node.getSpecializations()) {
-                if (current.isUninitialized() || current.isReachable()) {
+                if (current.isReachable()) {
                     continue;
                 }
                 if (firstUnreachable) {
@@ -1369,7 +1305,7 @@
             List<SpecializationData> specializations = node.getSpecializations();
             List<SpecializationData> filteredSpecializations = new ArrayList<>();
             for (SpecializationData current : specializations) {
-                if (current.isUninitialized() || !current.isReachable()) {
+                if (current.isUninitialized() || current.isPolymorphic() || !current.isReachable()) {
                     continue;
                 }
                 filteredSpecializations.add(current);
@@ -1402,7 +1338,7 @@
 
         private void emitUnreachableSpecializations(final CodeTreeBuilder builder, NodeData node) {
             for (SpecializationData current : node.getSpecializations()) {
-                if (current.isUninitialized() || current.isReachable()) {
+                if (current.isReachable()) {
                     continue;
                 }
                 builder.string("// unreachable ").string(current.getId()).newLine();
@@ -1520,19 +1456,15 @@
                     }
                 }
 
-                NodeChildData child = node.findChild(valueParam.getSpecification().getName());
-                if (child == null) {
-                    throw new IllegalStateException();
-                }
-
-                CodeTree implicitGuard = createTypeGuard(guardsBuilder, child, valueParam, typeGuard.getType(), typedCasts);
+                NodeExecutionData execution = valueParam.getSpecification().getExecution();
+                CodeTree implicitGuard = createTypeGuard(guardsBuilder, execution, valueParam, typeGuard.getType(), typedCasts);
                 if (implicitGuard != null) {
                     guardsBuilder.string(guardsAnd);
                     guardsBuilder.tree(implicitGuard);
                     guardsAnd = " && ";
                 }
 
-                CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType(), checkMinimumState, typedCasts);
+                CodeTree cast = createCast(castBuilder, execution, valueParam, typeGuard.getType(), checkMinimumState, typedCasts);
                 if (cast != null) {
                     castBuilder.tree(cast);
                 }
@@ -1604,8 +1536,8 @@
             return false;
         }
 
-        private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean typedCasts) {
-            NodeData node = field.getNodeData();
+        private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean typedCasts) {
+            NodeData node = execution.getChild().getNodeData();
 
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
 
@@ -1617,7 +1549,7 @@
 
             builder.startGroup();
 
-            if (field.isShortCircuit()) {
+            if (execution.isShortCircuit()) {
                 ActualParameter shortCircuit = source.getPreviousParameter();
                 assert shortCircuit != null;
                 builder.string("(");
@@ -1644,7 +1576,7 @@
             }
             builder.end().end(); // call
 
-            if (field.isShortCircuit()) {
+            if (execution.isShortCircuit()) {
                 builder.string(")");
             }
 
@@ -1654,8 +1586,8 @@
         }
 
         // TODO merge redundancies with #createTypeGuard
-        private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean checkMinimumState, boolean typedCasts) {
-            NodeData node = field.getNodeData();
+        private CodeTree createCast(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean checkMinimumState, boolean typedCasts) {
+            NodeData node = execution.getChild().getNodeData();
             TypeData sourceType = source.getTypeSystemType();
 
             if (!sourceType.needsCastTo(getContext(), targetType)) {
@@ -1663,7 +1595,7 @@
             }
 
             CodeTree condition = null;
-            if (field.isShortCircuit()) {
+            if (execution.isShortCircuit()) {
                 ActualParameter shortCircuit = source.getPreviousParameter();
                 assert shortCircuit != null;
                 condition = CodeTreeBuilder.singleString(valueName(shortCircuit));
@@ -1777,7 +1709,7 @@
             }
             builder.end();
             builder.startDoWhile();
-            builder.string("!").startParantheses().instanceOf("root", nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).end();
+            builder.string("!").startParantheses().instanceOf("root", nodePolymorphicClassName(node)).end();
             builder.end();
             return builder.getRoot();
         }
@@ -1808,7 +1740,7 @@
             }
             if (current.isGeneric()) {
                 builder.startReturn().tree(replace).string(".").startCall(EXECUTE_GENERIC_NAME);
-                addInternalValueParameterNames(builder, source, current, null, current.getNode().needsFrame(getContext()), true, null);
+                addInternalValueParameterNames(builder, source, current, null, current.getNode().needsFrame(getContext()), null);
                 builder.end().end();
             } else if (current.getMethod() == null) {
                 if (replaceCall != null) {
@@ -1836,11 +1768,8 @@
                 replaceCall.startCall("replace");
             }
             replaceCall.startGroup().startNew(className).string(source);
-            for (ActualParameter param : current.getParameters()) {
-                if (!param.getSpecification().isSignature()) {
-                    continue;
-                }
-                NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
+            for (ActualParameter param : current.getSignatureParameters()) {
+                NodeChildData child = param.getSpecification().getExecution().getChild();
                 List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
                 if (types.size() > 1) {
                     replaceCall.string(implicitTypeName(param));
@@ -1858,7 +1787,7 @@
         }
 
         private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node, String currentNode) {
-            String polyClassName = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization());
+            String polyClassName = nodePolymorphicClassName(node);
             String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization());
             CodeTreeBuilder builder = parent.create();
 
@@ -1869,22 +1798,14 @@
             builder.startStatement().startCall("currentCopy", "setNext0").startNew(uninitializedName).string(currentNode).end().end().end();
 
             builder.startReturn();
-            builder.startCall("currentCopy.next0", executeCachedName(node.getGenericPolymorphicSpecialization()));
-            addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, true, null);
+            builder.startCall("currentCopy.next0", EXECUTE_POLYMORPHIC_NAME);
+            addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, null);
             builder.end();
             builder.end();
 
             return builder.getRoot();
         }
 
-        private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) {
-            for (TemplateMethod listener : node.getSpecializationListeners()) {
-                builder.startStatement();
-                builder.tree(createTemplateMethodCall(builder, null, listener, listener, null));
-                builder.end(); // statement
-            }
-        }
-
         protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) {
             TypeData type = executable.getType();
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
@@ -1897,11 +1818,7 @@
             boolean returnVoid = type.isVoid();
 
             List<ActualParameter> executeParameters = new ArrayList<>();
-            for (ActualParameter sourceParameter : executable.getParameters()) {
-                if (!sourceParameter.getSpecification().isSignature()) {
-                    continue;
-                }
-
+            for (ActualParameter sourceParameter : executable.getSignatureParameters()) {
                 ActualParameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName());
                 if (targetParameter != null) {
                     executeParameters.add(targetParameter);
@@ -1968,14 +1885,13 @@
         protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters,
                         ActualParameter unexpectedParameter) {
             CodeTreeBuilder builder = parent.create();
-            NodeData node = specialization.getNode();
             for (ActualParameter targetParameter : targetParameters) {
-                NodeChildData child = node.findChild(targetParameter.getSpecification().getName());
                 if (!targetParameter.getSpecification().isSignature()) {
                     continue;
                 }
-                CodeTree executionExpressions = createExecuteChild(builder, child, sourceExecutable, targetParameter, unexpectedParameter);
-                CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, specialization, sourceExecutable, targetParameter, isShortCircuit(child), unexpectedParameter);
+                NodeExecutionData execution = targetParameter.getSpecification().getExecution();
+                CodeTree executionExpressions = createExecuteChild(builder, execution, sourceExecutable, targetParameter, unexpectedParameter);
+                CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, specialization, sourceExecutable, targetParameter, execution.isShortCircuit(), unexpectedParameter);
                 CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, specialization, targetParameter, unexpectedParameter);
 
                 if (shortCircuitTree == executionExpressions) {
@@ -1993,15 +1909,16 @@
             return builder.getRoot();
         }
 
-        private ExecutableTypeData resolveExecutableType(NodeChildData child, TypeData type) {
-            ExecutableTypeData targetExecutable = child.findExecutableType(getContext(), type);
+        private ExecutableTypeData resolveExecutableType(NodeExecutionData execution, TypeData type) {
+            ExecutableTypeData targetExecutable = execution.getChild().findExecutableType(getContext(), type);
             if (targetExecutable == null) {
-                targetExecutable = child.findAnyGenericExecutableType(getContext());
+                targetExecutable = execution.getChild().findAnyGenericExecutableType(getContext());
             }
             return targetExecutable;
         }
 
-        private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ActualParameter targetParameter, ActualParameter unexpectedParameter) {
+        private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, ActualParameter targetParameter,
+                        ActualParameter unexpectedParameter) {
             SpecializationData specialization = getModel();
             TreeSet<TypeData> possiblePolymorphicTypes = lookupPolymorphicTargetTypes(targetParameter);
             if (specialization.isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null && possiblePolymorphicTypes.size() > 1) {
@@ -2020,28 +1937,25 @@
                     builder.string(polymorphicTypeName(targetParameter)).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType());
                     builder.end().startBlock();
                     builder.startStatement();
-                    builder.tree(createExecuteChildExpression(parent, child, sourceType, new ActualParameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null));
+                    builder.tree(createExecuteChildExpression(parent, execution, sourceType, new ActualParameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null));
                     builder.end();
                     builder.end();
                 }
 
                 builder.startElseBlock();
-                builder.startStatement().tree(createExecuteChildImplicit(parent, child, sourceExecutable, targetParameter, unexpectedParameter)).end();
+                builder.startStatement().tree(createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter)).end();
                 builder.end();
 
                 return builder.getRoot();
             } else {
-                return createExecuteChildImplicit(parent, child, sourceExecutable, targetParameter, unexpectedParameter);
+                return createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter);
             }
         }
 
         protected final List<ActualParameter> getImplicitTypeParamters(SpecializationData model) {
             List<ActualParameter> parameter = new ArrayList<>();
-            for (ActualParameter param : model.getParameters()) {
-                if (!param.getSpecification().isSignature()) {
-                    continue;
-                }
-                NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
+            for (ActualParameter param : model.getSignatureParameters()) {
+                NodeChildData child = param.getSpecification().getExecution().getChild();
                 List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
                 if (types.size() > 1) {
                     parameter.add(param);
@@ -2065,7 +1979,7 @@
             return possiblePolymorphicTypes;
         }
 
-        private CodeTree createExecuteChildImplicit(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ActualParameter param, ActualParameter unexpectedParameter) {
+        private CodeTree createExecuteChildImplicit(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, ActualParameter param, ActualParameter unexpectedParameter) {
             CodeTreeBuilder builder = parent.create();
             ActualParameter sourceParameter = sourceExecutable.findParameter(param.getLocalName());
             String childExecuteName = createExecuteChildMethodName(param, sourceParameter != null);
@@ -2089,19 +2003,20 @@
 
                 builder.end();
             } else {
-                List<TypeData> sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
+                List<TypeData> sourceTypes = execution.getChild().getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
                 TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null;
                 if (sourceTypes.size() > 1) {
                     builder.tree(createExecuteChildImplicitExpressions(parent, param, expectType));
                 } else {
-                    builder.tree(createExecuteChildExpression(parent, child, expectType, param, unexpectedParameter, null));
+                    builder.tree(createExecuteChildExpression(parent, execution, expectType, param, unexpectedParameter, null));
                 }
             }
             return builder.getRoot();
         }
 
         private String createExecuteChildMethodName(ActualParameter param, boolean expect) {
-            NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
+            NodeExecutionData execution = param.getSpecification().getExecution();
+            NodeChildData child = execution.getChild();
             if (child.getExecuteWith().size() > 0) {
                 return null;
             }
@@ -2110,7 +2025,8 @@
                 return null;
             }
             String prefix = expect ? "expect" : "execute";
-            return prefix + Utils.firstLetterUpperCase(child.getName()) + Utils.firstLetterUpperCase(Utils.getSimpleName(param.getType())) + param.getSpecificationIndex();
+            String suffix = execution.getIndex() > -1 ? String.valueOf(execution.getIndex()) : "";
+            return prefix + Utils.firstLetterUpperCase(child.getName()) + Utils.firstLetterUpperCase(Utils.getSimpleName(param.getType())) + suffix;
         }
 
         private List<CodeExecutableElement> createExecuteChilds(ActualParameter param, Set<TypeData> expectTypes) {
@@ -2155,7 +2071,7 @@
         private CodeTree createExecuteChildImplicitExpressions(CodeTreeBuilder parent, ActualParameter targetParameter, TypeData expectType) {
             CodeTreeBuilder builder = parent.create();
             NodeData node = getModel().getNode();
-            NodeChildData child = node.findChild(targetParameter.getSpecification().getName());
+            NodeExecutionData execution = targetParameter.getSpecification().getExecution();
             List<TypeData> sourceTypes = node.getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType());
             boolean elseIf = false;
             int index = 0;
@@ -2169,18 +2085,18 @@
                     builder.startElseBlock();
                 }
 
-                ExecutableTypeData implictExecutableTypeData = child.findExecutableType(getContext(), sourceType);
+                ExecutableTypeData implictExecutableTypeData = execution.getChild().findExecutableType(getContext(), sourceType);
                 if (implictExecutableTypeData == null) {
                     /*
                      * For children with executeWith.size() > 0 an executable type may not exist so
                      * use the generic executable type which is guaranteed to exist. An expect call
                      * is inserted automatically by #createExecuteExpression.
                      */
-                    implictExecutableTypeData = child.getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), child.getExecuteWith().size());
+                    implictExecutableTypeData = execution.getChild().getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), execution.getChild().getExecuteWith().size());
                 }
 
-                ImplicitCastData cast = child.getNodeData().getTypeSystem().lookupCast(sourceType, targetParameter.getTypeSystemType());
-                CodeTree execute = createExecuteChildExpression(builder, child, expectType, targetParameter, null, cast);
+                ImplicitCastData cast = execution.getChild().getNodeData().getTypeSystem().lookupCast(sourceType, targetParameter.getTypeSystemType());
+                CodeTree execute = createExecuteChildExpression(builder, execution, expectType, targetParameter, null, cast);
                 builder.statement(execute);
                 builder.end();
                 index++;
@@ -2188,8 +2104,8 @@
             return builder.getRoot();
         }
 
-        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData child, TypeData sourceParameterType, ActualParameter targetParameter, ActualParameter unexpectedParameter,
-                        ImplicitCastData cast) {
+        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData execution, TypeData sourceParameterType, ActualParameter targetParameter,
+                        ActualParameter unexpectedParameter, ImplicitCastData cast) {
             // assignments: targetType <- castTargetType <- castSourceType <- sourceType
             TypeData sourceType = sourceParameterType;
             TypeData targetType = targetParameter.getTypeSystemType();
@@ -2203,15 +2119,15 @@
 
             CodeTree expression;
             if (sourceType == null) {
-                ExecutableTypeData targetExecutable = resolveExecutableType(child, castSourceType);
-                expression = createExecuteChildExpression(parent, child, targetParameter, targetExecutable, unexpectedParameter);
+                ExecutableTypeData targetExecutable = resolveExecutableType(execution, castSourceType);
+                expression = createExecuteChildExpression(parent, execution, targetExecutable, unexpectedParameter);
                 sourceType = targetExecutable.getType();
             } else {
                 expression = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter));
             }
 
             // target = expectTargetType(implicitCast(expectCastSourceType(source)))
-            TypeSystemData typeSystem = child.getNodeData().getTypeSystem();
+            TypeSystemData typeSystem = execution.getChild().getNodeData().getTypeSystem();
             expression = createExpectType(typeSystem, sourceType, castSourceType, expression);
             expression = createImplicitCast(parent, typeSystem, cast, expression);
             expression = createExpectType(typeSystem, castTargetType, targetType, expression);
@@ -2248,32 +2164,32 @@
         }
 
         private boolean hasUnexpected(ActualParameter sourceParameter, ActualParameter targetParameter, ActualParameter unexpectedParameter) {
-            NodeChildData child = getModel().getNode().findChild(targetParameter.getSpecification().getName());
+            NodeExecutionData execution = targetParameter.getSpecification().getExecution();
 
             if (getModel().isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) {
                 // check for other polymorphic types
                 TreeSet<TypeData> polymorphicTargetTypes = lookupPolymorphicTargetTypes(targetParameter);
                 if (polymorphicTargetTypes.size() > 1) {
                     for (TypeData polymorphicTargetType : polymorphicTargetTypes) {
-                        if (hasUnexpectedType(child, sourceParameter, polymorphicTargetType)) {
+                        if (hasUnexpectedType(execution, sourceParameter, polymorphicTargetType)) {
                             return true;
                         }
                     }
                 }
             }
 
-            if (hasUnexpectedType(child, sourceParameter, targetParameter.getTypeSystemType())) {
+            if (hasUnexpectedType(execution, sourceParameter, targetParameter.getTypeSystemType())) {
                 return true;
             }
             return false;
         }
 
-        private boolean hasUnexpectedType(NodeChildData child, ActualParameter sourceParameter, TypeData targetType) {
+        private boolean hasUnexpectedType(NodeExecutionData execution, ActualParameter sourceParameter, TypeData targetType) {
             List<TypeData> implicitSourceTypes = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
 
             for (TypeData implicitSourceType : implicitSourceTypes) {
                 TypeData sourceType;
-                ExecutableTypeData targetExecutable = resolveExecutableType(child, implicitSourceType);
+                ExecutableTypeData targetExecutable = resolveExecutableType(execution, implicitSourceType);
                 if (sourceParameter != null) {
                     sourceType = sourceParameter.getTypeSystemType();
                 } else {
@@ -2336,8 +2252,7 @@
 
         private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, ActualParameter param) {
             NodeData node = specialization.getNode();
-            assert !node.getPolymorphicSpecializations().isEmpty();
-            SpecializationData generic = node.getGenericPolymorphicSpecialization();
+            SpecializationData polymorphic = node.getPolymorphicSpecialization();
 
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             builder.startStatement().string(polymorphicTypeName(param)).string(" = ").typeLiteral(getContext().getType(Object.class)).end();
@@ -2345,11 +2260,11 @@
             builder.startReturn();
 
             CodeTreeBuilder execute = new CodeTreeBuilder(builder);
-            execute.startCall("next0", executeCachedName(generic));
-            addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true, null);
+            execute.startCall("next0", EXECUTE_POLYMORPHIC_NAME);
+            addInternalValueParameterNames(execute, specialization, polymorphic, param.getLocalName(), true, null);
             execute.end();
 
-            TypeData sourceType = generic.getReturnType().getTypeSystemType();
+            TypeData sourceType = polymorphic.getReturnType().getTypeSystemType();
 
             builder.tree(createExpectExecutableType(node, sourceType, currentExecutable, execute.getRoot()));
 
@@ -2357,11 +2272,10 @@
             return builder.getRoot();
         }
 
-        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetChild, ActualParameter targetParameter, ExecutableTypeData targetExecutable,
-                        ActualParameter unexpectedParameter) {
+        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData targetExecution, ExecutableTypeData targetExecutable, ActualParameter unexpectedParameter) {
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            if (targetChild != null) {
-                builder.tree(createAccessChild(builder, targetChild, targetParameter));
+            if (targetExecution != null) {
+                builder.tree(createAccessChild(builder, targetExecution));
                 builder.string(".");
             }
 
@@ -2375,8 +2289,8 @@
                     builder.string(parameter.getLocalName());
                 } else {
 
-                    if (index < targetChild.getExecuteWith().size()) {
-                        NodeChildData child = targetChild.getExecuteWith().get(index);
+                    if (index < targetExecution.getChild().getExecuteWith().size()) {
+                        NodeChildData child = targetExecution.getChild().getExecuteWith().get(index);
 
                         ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName());
                         List<ActualParameter> specializationParams = getModel().findParameters(spec);
@@ -2415,31 +2329,31 @@
             return builder.getRoot();
         }
 
-        private CodeTree createAccessChild(CodeTreeBuilder parent, NodeChildData targetChild, ActualParameter targetParameter) throws AssertionError {
+        private CodeTree createAccessChild(CodeTreeBuilder parent, NodeExecutionData targetExecution) throws AssertionError {
             CodeTreeBuilder builder = parent.create();
-            Element accessElement = targetChild.getAccessElement();
+            Element accessElement = targetExecution.getChild().getAccessElement();
             if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) {
-                builder.string("this.").string(targetChild.getName());
+                builder.string("this.").string(targetExecution.getChild().getName());
             } else if (accessElement.getKind() == ElementKind.FIELD) {
                 builder.string("this.").string(accessElement.getSimpleName().toString());
             } else {
                 throw new AssertionError();
             }
-            if (targetParameter.getSpecification().isIndexed()) {
-                builder.string("[" + targetParameter.getSpecificationIndex() + "]");
+            if (targetExecution.isIndexed()) {
+                builder.string("[" + targetExecution.getIndex() + "]");
             }
             return builder.getRoot();
         }
 
         private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) {
-            NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName());
-            if (!isShortCircuit(forField)) {
+            NodeExecutionData execution = parameter.getSpecification().getExecution();
+            if (execution == null || !execution.isShortCircuit()) {
                 return body;
             }
 
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter);
-            builder.tree(createShortCircuitValue(builder, specialization, forField, shortCircuitParam, exceptionParam));
+            builder.tree(createShortCircuitValue(builder, specialization, execution, shortCircuitParam, exceptionParam));
             builder.declaration(parameter.getType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getType()));
             builder.startIf().string(shortCircuitParam.getLocalName()).end();
             builder.startBlock();
@@ -2454,16 +2368,13 @@
             return builder.getRoot();
         }
 
-        private boolean isShortCircuit(NodeChildData forField) {
-            return forField != null && forField.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT;
-        }
-
-        private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeChildData forField, ActualParameter shortCircuitParam, ActualParameter exceptionParam) {
+        private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeExecutionData execution, ActualParameter shortCircuitParam,
+                        ActualParameter exceptionParam) {
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             int shortCircuitIndex = 0;
-            for (NodeChildData field : specialization.getNode().getChildren()) {
-                if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) {
-                    if (field == forField) {
+            for (NodeExecutionData otherExectuion : specialization.getNode().getChildExecutions()) {
+                if (otherExectuion.isShortCircuit()) {
+                    if (otherExectuion == execution) {
                         break;
                     }
                     shortCircuitIndex++;
@@ -2484,7 +2395,7 @@
             CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
             specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);
             specializeCall.string(String.valueOf(node.getSpecializations().indexOf(current)));
-            addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true, null);
+            addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, null);
             specializeCall.doubleQuote(reason);
             specializeCall.end().end();
 
@@ -2543,14 +2454,11 @@
             if (nodeGen != null) {
                 baseType = nodeGen.asType();
             }
-            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node, polymorph), baseType, false);
+            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false);
 
             clazz.getAnnotationMirrors().add(createNodeInfo(node, Kind.POLYMORPHIC));
 
-            for (ActualParameter polymorphParameter : polymorph.getParameters()) {
-                if (!polymorphParameter.getSpecification().isSignature()) {
-                    continue;
-                }
+            for (ActualParameter polymorphParameter : polymorph.getSignatureParameters()) {
                 if (!polymorphParameter.getTypeSystemType().isGeneric()) {
                     continue;
                 }
@@ -2640,8 +2548,12 @@
                 kind = Kind.GENERIC;
             } else if (specialization.isUninitialized()) {
                 kind = Kind.UNINITIALIZED;
+            } else if (specialization.isPolymorphic()) {
+                kind = Kind.POLYMORPHIC;
+            } else if (specialization.isSpecialized()) {
+                kind = Kind.SPECIALIZED;
             } else {
-                kind = Kind.SPECIALIZED;
+                throw new AssertionError();
             }
             clazz.getAnnotationMirrors().add(createNodeInfo(node, kind));
 
@@ -2747,17 +2659,11 @@
 
             CodeTypeElement clazz = getElement();
 
-            final SpecializationData polymorphic = node.getGenericPolymorphicSpecialization();
-
-            ExecutableElement executeCached = nodeGen.getMethod(executeCachedName(polymorphic));
-            // ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached,
-            // node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType());
-
-            ExecutableTypeMethodParser parser = new ExecutableTypeMethodParser(getContext(), node);
-            ExecutableTypeData execType = parser.parse(Arrays.asList(executeCached)).get(0);
-
-            CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, false);
-            CodeTreeBuilder builder = executeMethod.getBuilder();
+            final SpecializationData polymorphic = node.getPolymorphicSpecialization();
+            ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_POLYMORPHIC_NAME);
+            CodeExecutableElement executeMethod = CodeExecutableElement.clone(getContext().getEnvironment(), executeCached);
+            executeMethod.getModifiers().remove(Modifier.ABSTRACT);
+            CodeTreeBuilder builder = executeMethod.createBuilder();
 
             if (specialization.isGeneric() || specialization.isPolymorphic()) {
                 builder.startThrow().startNew(getContext().getType(AssertionError.class));
@@ -2767,8 +2673,8 @@
                 builder.tree(createAppendPolymorphic(builder, specialization));
             } else {
                 CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder);
-                elseBuilder.startReturn().startCall("this.next0", executeCachedName(polymorphic));
-                addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true, null);
+                elseBuilder.startReturn().startCall("this.next0", EXECUTE_POLYMORPHIC_NAME);
+                addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, null);
                 elseBuilder.end().end();
 
                 boolean forceElse = specialization.getExceptions().size() > 0;
@@ -2797,7 +2703,7 @@
             builder.startBlock();
             String message = "Polymorphic limit reached (" + node.getPolymorphicDepth() + ")";
             String castRoot = "(" + baseClassName(node) + ") root";
-            builder.tree(createGenericInvoke(builder, node.getGenericPolymorphicSpecialization(), node.getGenericSpecialization(),
+            builder.tree(createGenericInvoke(builder, node.getPolymorphicSpecialization(), node.getGenericSpecialization(),
                             createReplaceCall(builder, node.getGenericSpecialization(), "root", castRoot, message), null));
             builder.end();
 
@@ -2809,13 +2715,13 @@
             CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder);
             specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);
             specializeCall.string("0");
-            addInternalValueParameterNames(specializeCall, specialization, node.getGenericSpecialization(), null, true, true, null);
+            addInternalValueParameterNames(specializeCall, specialization, node.getGenericSpecialization(), null, true, null);
             specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end();
             specializeCall.end().end();
 
             builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot());
 
-            CodeTree root = builder.create().cast(nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).string("root").getRoot();
+            CodeTree root = builder.create().cast(nodePolymorphicClassName(node)).string("root").getRoot();
             builder.startIf().string("this.next0 != null").end().startBlock();
             builder.startStatement().string("(").tree(root).string(").").startCall(UPDATE_TYPES_NAME).tree(root).end().end();
             builder.end();
@@ -2856,39 +2762,43 @@
             int signatureIndex = -1;
             for (VariableElement param : method.getParameters()) {
                 CodeVariableElement var = CodeVariableElement.clone(param);
-                ActualParameter actualParameter = execType.getParameters().get(i);
-                if (actualParameter.getSpecification().isSignature()) {
-                    signatureIndex++;
-                }
-
+                ActualParameter actualParameter = i < execType.getParameters().size() ? execType.getParameters().get(i) : null;
                 String name;
-                if (evaluated && actualParameter.getSpecification().isSignature()) {
-                    name = valueNameEvaluated(actualParameter);
-                } else {
-                    name = valueName(actualParameter);
-                }
-
-                int varArgCount = getModel().getSignatureSize() - signatureIndex;
-                if (evaluated && actualParameter.isVarArgs()) {
-                    ActualParameter baseVarArgs = actualParameter;
-                    name = valueName(baseVarArgs) + "Args";
-
-                    builder.startAssert().string(name).string(" != null").end();
-                    builder.startAssert().string(name).string(".length == ").string(String.valueOf(varArgCount)).end();
-                    if (varArgCount > 0) {
-                        List<ActualParameter> varArgsParameter = execType.getParameters().subList(i, execType.getParameters().size());
-                        for (ActualParameter varArg : varArgsParameter) {
-                            if (varArgCount <= 0) {
-                                break;
+                if (actualParameter != null) {
+                    if (actualParameter.getSpecification().isSignature()) {
+                        signatureIndex++;
+                    }
+
+                    if (evaluated && actualParameter.getSpecification().isSignature()) {
+                        name = valueNameEvaluated(actualParameter);
+                    } else {
+                        name = valueName(actualParameter);
+                    }
+
+                    int varArgCount = getModel().getSignatureSize() - signatureIndex;
+                    if (evaluated && actualParameter.isTypeVarArgs()) {
+                        ActualParameter baseVarArgs = actualParameter;
+                        name = valueName(baseVarArgs) + "Args";
+
+                        builder.startAssert().string(name).string(" != null").end();
+                        builder.startAssert().string(name).string(".length == ").string(String.valueOf(varArgCount)).end();
+                        if (varArgCount > 0) {
+                            List<ActualParameter> varArgsParameter = execType.getParameters().subList(i, execType.getParameters().size());
+                            for (ActualParameter varArg : varArgsParameter) {
+                                if (varArgCount <= 0) {
+                                    break;
+                                }
+                                TypeMirror type = baseVarArgs.getType();
+                                if (type.getKind() == TypeKind.ARRAY) {
+                                    type = ((ArrayType) type).getComponentType();
+                                }
+                                builder.declaration(type, valueNameEvaluated(varArg), name + "[" + varArg.getTypeVarArgsIndex() + "]");
+                                varArgCount--;
                             }
-                            TypeMirror type = baseVarArgs.getType();
-                            if (type.getKind() == TypeKind.ARRAY) {
-                                type = ((ArrayType) type).getComponentType();
-                            }
-                            builder.declaration(type, valueNameEvaluated(varArg), name + "[" + varArg.getVarArgsIndex() + "]");
-                            varArgCount--;
                         }
                     }
+                } else {
+                    name = "arg" + i;
                 }
                 var.setName(name);
                 method.getParameters().set(i, var);
@@ -2984,58 +2894,42 @@
 
             CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent);
             if (specialization.isPolymorphic()) {
-                returnBuilder.startCall("next0", executeCachedName(specialization));
-                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true, null);
+                returnBuilder.startCall("next0", EXECUTE_POLYMORPHIC_NAME);
+                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null);
                 returnBuilder.end();
             } else if (specialization.isUninitialized()) {
                 returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME);
                 returnBuilder.string("0");
-                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true, null);
+                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null);
                 returnBuilder.doubleQuote("Uninitialized monomorphic");
                 returnBuilder.end();
             } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
                 emitEncounteredSynthetic(builder, specialization);
             } else if (specialization.isGeneric()) {
                 returnBuilder.startCall("super", EXECUTE_GENERIC_NAME);
-                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, node.needsFrame(getContext()), true, null);
+                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, node.needsFrame(getContext()), null);
                 returnBuilder.end();
             } else {
                 returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null));
             }
 
             if (!returnBuilder.isEmpty()) {
-                ExecutableTypeData sourceExecutableType = node.findExecutableType(specialization.getReturnType().getTypeSystemType(), 0);
-                boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext());
-                boolean targetSupportsUnexpected = executable.hasUnexpectedValue(getContext());
-
                 TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType());
                 TypeData sourceType = specialization.getReturnType().getTypeSystemType();
 
-                if (specialization.isPolymorphic() && sourceThrowsUnexpected && !targetSupportsUnexpected) {
-                    builder.startTryBlock();
-                }
                 builder.startReturn();
                 if (targetType == null || sourceType == null) {
                     builder.tree(returnBuilder.getRoot());
                 } else if (sourceType.needsCastTo(getContext(), targetType)) {
-                    builder.tree(createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.expectTypeMethodName(targetType), returnBuilder.getRoot()));
+                    String castMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType);
+                    if (!executable.hasUnexpectedValue(context)) {
+                        castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
+                    }
+                    builder.tree(createCallTypeSystemMethod(context, parent, node, castMethodName, returnBuilder.getRoot()));
                 } else {
                     builder.tree(returnBuilder.getRoot());
                 }
                 builder.end();
-                if (specialization.isPolymorphic() && sourceThrowsUnexpected && !targetSupportsUnexpected) {
-                    builder.end();
-                    builder.startCatchBlock(getUnexpectedValueException(), "ex");
-                    builder.startReturn();
-                    CodeTree returns = CodeTreeBuilder.singleString("ex.getResult()");
-                    if (sourceType.needsCastTo(getContext(), targetType)) {
-                        builder.tree(createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), returns));
-                    } else {
-                        builder.tree(returns);
-                    }
-                    builder.end();
-                    builder.end();
-                }
             }
 
             if (!specialization.getExceptions().isEmpty()) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java	Tue Jan 07 22:36:23 2014 +0100
@@ -35,47 +35,62 @@
 public class NodeData extends Template implements Comparable<NodeData> {
 
     private final String nodeId;
+    private final String shortName;
+    private final List<NodeData> enclosingNodes = new ArrayList<>();
     private NodeData declaringNode;
-    private List<NodeData> declaredNodes = new ArrayList<>();
-    private boolean nodeContainer;
 
-    private TypeSystemData typeSystem;
-    private List<NodeChildData> children;
-    private List<NodeFieldData> fields;
-    private TypeMirror nodeType;
+    private final TypeSystemData typeSystem;
+    private final List<NodeChildData> children;
+    private final List<NodeExecutionData> childExecutions;
+    private final List<NodeFieldData> fields;
+    private final List<String> assumptions;
+
     private ParameterSpec instanceParameterSpec;
 
-    private List<SpecializationData> specializations;
-    private List<SpecializationData> polymorphicSpecializations;
-    private SpecializationData genericPolymorphicSpecialization;
-    private List<SpecializationListenerData> specializationListeners;
+    private final List<SpecializationData> specializations = new ArrayList<>();
+    private final List<ShortCircuitData> shortCircuits = new ArrayList<>();
+    private final List<CreateCastData> casts = new ArrayList<>();
     private Map<Integer, List<ExecutableTypeData>> executableTypes;
-    private List<ShortCircuitData> shortCircuits;
-    private List<String> assumptions;
-    private List<CreateCastData> casts;
+
+    private final NodeExecutionData thisExecution;
 
     private int polymorphicDepth = -1;
-    private String shortName;
 
-    public NodeData(TypeElement type, String id) {
+    public NodeData(TypeElement type, String shortName, TypeSystemData typeSystem, List<NodeChildData> children, List<NodeExecutionData> executions, List<NodeFieldData> fields,
+                    List<String> assumptions, int polymorphicDepth) {
         super(type, null, null);
-        this.nodeId = id;
+        this.nodeId = type.getSimpleName().toString();
+        this.shortName = shortName;
+        this.typeSystem = typeSystem;
+        this.fields = fields;
+        this.children = children;
+        this.childExecutions = executions;
+        this.assumptions = assumptions;
+        this.polymorphicDepth = polymorphicDepth;
+        this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, false);
+        this.thisExecution.getChild().setNode(this);
+        if (children != null) {
+            for (NodeChildData child : children) {
+                child.setParentNode(this);
+            }
+        }
     }
 
-    public NodeData(NodeData splitSource, String templateMethodName, String nodeId) {
-        super(splitSource.getTemplateType(), templateMethodName, null);
-        this.nodeId = nodeId;
-        this.declaringNode = splitSource.declaringNode;
-        this.declaredNodes = splitSource.declaredNodes;
-        this.typeSystem = splitSource.typeSystem;
-        this.nodeType = splitSource.nodeType;
-        this.specializations = splitSource.specializations;
-        this.specializationListeners = splitSource.specializationListeners;
-        this.executableTypes = splitSource.executableTypes;
-        this.shortCircuits = splitSource.shortCircuits;
-        this.fields = splitSource.fields;
-        this.children = splitSource.children;
-        this.assumptions = splitSource.assumptions;
+    public NodeData(TypeElement type) {
+        this(type, null, null, null, null, null, null, -1);
+    }
+
+    public NodeExecutionData getThisExecution() {
+        return thisExecution;
+    }
+
+    public void addEnclosedNode(NodeData node) {
+        this.enclosingNodes.add(node);
+        node.declaringNode = this;
+    }
+
+    public List<NodeExecutionData> getChildExecutions() {
+        return childExecutions;
     }
 
     public int getSignatureSize() {
@@ -114,7 +129,7 @@
         return polymorphicDepth > 1;
     }
 
-    void setPolymorphicDepth(int polymorphicDepth) {
+    public void setPolymorphicDepth(int polymorphicDepth) {
         this.polymorphicDepth = polymorphicDepth;
     }
 
@@ -122,43 +137,19 @@
         return casts;
     }
 
-    void setCasts(List<CreateCastData> casts) {
-        this.casts = casts;
-    }
-
-    void setShortName(String shortName) {
-        this.shortName = shortName;
-    }
-
     public String getShortName() {
         return shortName;
     }
 
-    public boolean isNodeContainer() {
-        return nodeContainer;
-    }
-
-    void setTypeSystem(TypeSystemData typeSystem) {
-        this.typeSystem = typeSystem;
-    }
-
-    void setFields(List<NodeFieldData> fields) {
-        this.fields = fields;
-    }
-
     public List<NodeFieldData> getFields() {
         return fields;
     }
 
-    void setNodeContainer(boolean splitByMethodName) {
-        this.nodeContainer = splitByMethodName;
-    }
-
     @Override
     protected List<MessageContainer> findChildContainers() {
         List<MessageContainer> containerChildren = new ArrayList<>();
-        if (declaredNodes != null) {
-            containerChildren.addAll(declaredNodes);
+        if (enclosingNodes != null) {
+            containerChildren.addAll(enclosingNodes);
         }
         if (typeSystem != null) {
             containerChildren.add(typeSystem);
@@ -170,9 +161,6 @@
                 }
             }
         }
-        if (specializationListeners != null) {
-            containerChildren.addAll(specializationListeners);
-        }
         if (executableTypes != null) {
             containerChildren.addAll(getExecutableTypes());
         }
@@ -204,16 +192,9 @@
     }
 
     public TypeMirror getNodeType() {
-        if (nodeType != null) {
-            return nodeType;
-        }
         return getTemplateType().asType();
     }
 
-    void setAssumptions(List<String> assumptions) {
-        this.assumptions = assumptions;
-    }
-
     public List<String> getAssumptions() {
         return assumptions;
     }
@@ -228,7 +209,7 @@
 
         boolean noSpecialization = true;
         for (SpecializationData specialization : specializations) {
-            noSpecialization = noSpecialization && specialization.isGeneric() || specialization.isUninitialized();
+            noSpecialization = noSpecialization && !specialization.isSpecialized();
         }
         return !noSpecialization;
     }
@@ -246,7 +227,7 @@
 
     public List<NodeData> getNodeDeclaringChildren() {
         List<NodeData> nodeChildren = new ArrayList<>();
-        for (NodeData child : getDeclaredNodes()) {
+        for (NodeData child : getEnclosingNodes()) {
             if (child.needsFactory()) {
                 nodeChildren.add(child);
             }
@@ -255,24 +236,12 @@
         return nodeChildren;
     }
 
-    void setDeclaredNodes(List<NodeData> declaredChildren) {
-        this.declaredNodes = declaredChildren;
-
-        for (NodeData child : declaredChildren) {
-            child.declaringNode = this;
-        }
-    }
-
-    public NodeData getParent() {
+    public NodeData getDeclaringNode() {
         return declaringNode;
     }
 
-    public List<NodeData> getDeclaredNodes() {
-        return declaredNodes;
-    }
-
-    public void setNodeType(TypeMirror nodeType) {
-        this.nodeType = nodeType;
+    public List<NodeData> getEnclosingNodes() {
+        return enclosingNodes;
     }
 
     public List<TemplateMethod> getAllTemplateMethods() {
@@ -282,7 +251,6 @@
             methods.add(specialization);
         }
 
-        methods.addAll(getSpecializationListeners());
         methods.addAll(getExecutableTypes());
         methods.addAll(getShortCircuits());
         if (getCasts() != null) {
@@ -374,16 +342,6 @@
         return result;
     }
 
-    public NodeChildData[] filterFields(ExecutionKind usage) {
-        List<NodeChildData> filteredFields = new ArrayList<>();
-        for (NodeChildData field : getChildren()) {
-            if (usage == null || field.getExecutionKind() == usage) {
-                filteredFields.add(field);
-            }
-        }
-        return filteredFields.toArray(new NodeChildData[filteredFields.size()]);
-    }
-
     public boolean needsRewrites(ProcessorContext context) {
         boolean needsRewrites = false;
 
@@ -396,6 +354,15 @@
         return needsRewrites || getSpecializations().size() > 1;
     }
 
+    public SpecializationData getPolymorphicSpecialization() {
+        for (SpecializationData specialization : specializations) {
+            if (specialization.isPolymorphic()) {
+                return specialization;
+            }
+        }
+        return null;
+    }
+
     public SpecializationData getGenericSpecialization() {
         for (SpecializationData specialization : specializations) {
             if (specialization.isGeneric()) {
@@ -438,13 +405,12 @@
         dumpProperty(builder, indent, "executableTypes", getExecutableTypes());
         dumpProperty(builder, indent, "specializations", getSpecializations());
         dumpProperty(builder, indent, "polymorphicDepth", getPolymorphicDepth());
-        dumpProperty(builder, indent, "polymorphic", getPolymorphicSpecializations());
         dumpProperty(builder, indent, "assumptions", getAssumptions());
         dumpProperty(builder, indent, "casts", getCasts());
         dumpProperty(builder, indent, "messages", collectMessages());
-        if (getDeclaredNodes().size() > 0) {
+        if (getEnclosingNodes().size() > 0) {
             builder.append(String.format("\n%s  children = [", indent));
-            for (NodeData node : getDeclaredNodes()) {
+            for (NodeData node : getEnclosingNodes()) {
                 builder.append("\n");
                 builder.append(node.dump(level + 1));
             }
@@ -490,6 +456,18 @@
         return b.toString();
     }
 
+    public NodeExecutionData findExecution(String name) {
+        if (getChildExecutions() == null) {
+            return null;
+        }
+        for (NodeExecutionData execution : getChildExecutions()) {
+            if (execution.getName().equals(name)) {
+                return execution;
+            }
+        }
+        return null;
+    }
+
     public NodeChildData findChild(String name) {
         for (NodeChildData field : getChildren()) {
             if (field.getName().equals(name)) {
@@ -503,30 +481,8 @@
         return children;
     }
 
-    void setChildren(List<NodeChildData> fields) {
-        this.children = fields;
-    }
-
     public List<SpecializationData> getSpecializations() {
-        return getSpecializations(false);
-    }
-
-    public List<SpecializationData> getSpecializations(boolean userDefinedOnly) {
-        if (userDefinedOnly) {
-            List<SpecializationData> specs = new ArrayList<>();
-            for (SpecializationData spec : specializations) {
-                if (spec.getMethod() != null) {
-                    specs.add(spec);
-                }
-            }
-            return specs;
-        } else {
-            return specializations;
-        }
-    }
-
-    public List<SpecializationListenerData> getSpecializationListeners() {
-        return specializationListeners;
+        return specializations;
     }
 
     public List<ExecutableTypeData> getExecutableTypes() {
@@ -537,43 +493,10 @@
         return shortCircuits;
     }
 
-    void setSpecializations(List<SpecializationData> specializations) {
-        this.specializations = specializations;
-        if (this.specializations != null) {
-            for (SpecializationData specialization : specializations) {
-                specialization.setNode(this);
-            }
-        }
-    }
-
-    void setPolymorphicSpecializations(List<SpecializationData> polymorphicSpecializations) {
-        this.polymorphicSpecializations = polymorphicSpecializations;
-    }
-
-    public List<SpecializationData> getPolymorphicSpecializations() {
-        return polymorphicSpecializations;
-    }
-
-    void setGenericPolymorphicSpecialization(SpecializationData genericPolymoprhicSpecialization) {
-        this.genericPolymorphicSpecialization = genericPolymoprhicSpecialization;
-    }
-
-    public SpecializationData getGenericPolymorphicSpecialization() {
-        return genericPolymorphicSpecialization;
-    }
-
-    void setSpecializationListeners(List<SpecializationListenerData> specializationListeners) {
-        this.specializationListeners = specializationListeners;
-    }
-
-    void setExecutableTypes(Map<Integer, List<ExecutableTypeData>> executableTypes) {
+    public void setExecutableTypes(Map<Integer, List<ExecutableTypeData>> executableTypes) {
         this.executableTypes = executableTypes;
     }
 
-    void setShortCircuits(List<ShortCircuitData> shortCircuits) {
-        this.shortCircuits = shortCircuits;
-    }
-
     @Override
     public String toString() {
         return getClass().getSimpleName() + "[" + getNodeId() + "]";
@@ -593,4 +516,5 @@
     public int compareTo(NodeData o) {
         return getNodeId().compareTo(o.getNodeId());
     }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeExecutionData.java	Tue Jan 07 22:36:23 2014 +0100
@@ -0,0 +1,92 @@
+/*
+ * 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.node;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
+
+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/node/NodeMethodParser.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java	Tue Jan 07 22:36:23 2014 +0100
@@ -28,7 +28,6 @@
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
 import com.oracle.truffle.dsl.processor.template.*;
 
 public abstract class NodeMethodParser<E extends TemplateMethod> extends TemplateMethodParser<NodeData, E> {
@@ -41,10 +40,9 @@
         return template;
     }
 
-    @SuppressWarnings("unused")
-    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, int evaluatedCount) {
-        ParameterSpec spec = new ParameterSpec(valueName, nodeTypeMirrors(nodeData));
-        spec.setSignature(true);
+    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
+        ParameterSpec spec = new ParameterSpec(execution.getName(), nodeTypeMirrors(execution.getChild().getNodeData()));
+        spec.setExecution(execution);
         return spec;
     }
 
@@ -61,7 +59,9 @@
     }
 
     protected ParameterSpec createReturnParameterSpec() {
-        return createValueParameterSpec("returnValue", getNode(), 0);
+        ParameterSpec returnValue = new ParameterSpec("returnValue", nodeTypeMirrors(getNode()));
+        returnValue.setExecution(getNode().getThisExecution());
+        return returnValue;
     }
 
     @Override
@@ -78,38 +78,27 @@
         MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec());
 
         addDefaultFrame(methodSpec);
-        addDefaultImplicitThis(method, methodSpec);
         addDefaultFieldMethodSpec(methodSpec);
         addDefaultChildren(shortCircuitsEnabled, shortCircuitName, methodSpec);
 
         return methodSpec;
     }
 
-    public void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec methodSpec) {
-        // children are null when parsing executable types
-        if (getNode().getChildren() != null) {
-            for (NodeChildData child : getNode().getChildren()) {
-                String valueName = child.getName();
-                if (breakName != null && valueName.equals(breakName)) {
-                    break;
-                }
-                if (child.getExecutionKind() == ExecutionKind.DEFAULT) {
-                    ParameterSpec spec = createValueParameterSpec(child.getName(), child.getNodeData(), child.getExecuteWith().size());
-                    if (child.getCardinality().isMany()) {
-                        spec.setCardinality(Cardinality.MANY);
-                        spec.setIndexed(true);
-                    }
-                    methodSpec.addRequired(spec);
-                } else if (child.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) {
+    public void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec spec) {
+        if (getNode().getChildren() == null) {
+            // children are null when parsing executable types
+            return;
+        }
 
-                    if (shortCircuitsEnabled) {
-                        methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class)));
-                    }
-                    methodSpec.addRequired(createValueParameterSpec(valueName, child.getNodeData(), child.getExecuteWith().size()));
-                } else {
-                    assert false;
-                }
+        for (NodeExecutionData execution : getNode().getChildExecutions()) {
+            if (breakName != null && execution.getShortCircuitId().equals(breakName)) {
+                break;
             }
+
+            if (execution.isShortCircuit() && shortCircuitsEnabled) {
+                spec.addRequired(new ParameterSpec(shortCircuitValueName(execution.getName()), getContext().getType(boolean.class)));
+            }
+            spec.addRequired(createValueParameterSpec(execution));
         }
     }
 
@@ -121,7 +110,7 @@
 
     protected void addDefaultFieldMethodSpec(MethodSpec methodSpec) {
         for (NodeFieldData field : getNode().getFields()) {
-            if (getNode().isNodeContainer() || field.getGetter() == null) {
+            if (field.getGetter() == null) {
                 ParameterSpec spec = new ParameterSpec(field.getName(), field.getType());
                 spec.setLocal(true);
                 methodSpec.addOptional(spec);
@@ -129,14 +118,6 @@
         }
     }
 
-    protected void addDefaultImplicitThis(ExecutableElement method, MethodSpec methodSpec) {
-        TypeMirror declaredType = Utils.findNearestEnclosingType(method).asType();
-
-        if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(getContext(), declaredType, getContext().getTruffleTypes().getNode())) {
-            methodSpec.addImplicitRequiredType(getNode().getTemplateType().asType());
-        }
-    }
-
     private static String shortCircuitValueName(String valueName) {
         return "has" + Utils.firstLetterUpperCase(valueName);
     }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Tue Jan 07 22:36:23 2014 +0100
@@ -34,15 +34,15 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind;
+import com.oracle.truffle.dsl.processor.node.SpecializationData.SpecializationKind;
 import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature;
+import com.oracle.truffle.dsl.processor.template.TemplateMethod.TypeSignature;
 import com.oracle.truffle.dsl.processor.typesystem.*;
 
-public class NodeParser extends TemplateParser<NodeData> {
+public class NodeParser extends AbstractParser<NodeData> {
 
-    public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class,
-                    NodeContainer.class, NodeChild.class, NodeChildren.class, NodeId.class);
+    public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class,
+                    NodeChildren.class);
 
     private Map<String, NodeData> parsedNodes;
 
@@ -52,7 +52,6 @@
 
     @Override
     protected NodeData parse(Element element, AnnotationMirror mirror) {
-        assert element instanceof TypeElement;
         NodeData node = null;
         try {
             parsedNodes = new HashMap<>();
@@ -73,7 +72,7 @@
 
     @Override
     protected NodeData filterErrorElements(NodeData model) {
-        for (Iterator<NodeData> iterator = model.getDeclaredNodes().iterator(); iterator.hasNext();) {
+        for (Iterator<NodeData> iterator = model.getEnclosingNodes().iterator(); iterator.hasNext();) {
             NodeData node = filterErrorElements(iterator.next());
             if (node == null) {
                 iterator.remove();
@@ -106,29 +105,27 @@
             return parsedNodes.get(typeName);
         }
 
-        List<? extends TypeElement> types = ElementFilter.typesIn(rootType.getEnclosedElements());
-
-        List<NodeData> children = new ArrayList<>();
-        for (TypeElement childElement : types) {
-            NodeData childNode = resolveNode(childElement);
-            if (childNode != null) {
-                children.add(childNode);
+        List<NodeData> enclosedNodes = new ArrayList<>();
+        for (TypeElement enclosedType : ElementFilter.typesIn(rootType.getEnclosedElements())) {
+            NodeData enclosedChild = resolveNode(enclosedType);
+            if (enclosedChild != null) {
+                enclosedNodes.add(enclosedChild);
             }
         }
 
-        NodeData rootNode = parseNode(rootType);
-        if (rootNode == null && children.size() > 0) {
-            rootNode = new NodeData(rootType, rootType.getSimpleName().toString());
+        NodeData node = parseNode(rootType);
+        if (node == null && !enclosedNodes.isEmpty()) {
+            node = new NodeData(rootType);
         }
 
-        parsedNodes.put(typeName, rootNode);
-
-        if (rootNode != null) {
-            children.addAll(rootNode.getDeclaredNodes());
-            rootNode.setDeclaredNodes(children);
+        if (node != null) {
+            for (NodeData enclosedNode : enclosedNodes) {
+                node.addEnclosedNode(enclosedNode);
+            }
         }
 
-        return rootNode;
+        parsedNodes.put(typeName, node);
+        return node;
     }
 
     private NodeData parseNode(TypeElement originalTemplateType) {
@@ -140,174 +137,69 @@
             return null;
         }
 
-        List<TypeElement> lookupTypes = findSuperClasses(new ArrayList<TypeElement>(), templateType);
-        Collections.reverse(lookupTypes);
-
-        AnnotationMirror nodeClass = findFirstAnnotation(lookupTypes, NodeContainer.class);
-        TypeMirror nodeType = null;
-        if (Utils.isAssignable(context, templateType.asType(), context.getTruffleTypes().getNode())) {
-            nodeType = templateType.asType();
-        }
-        if (nodeClass != null) {
-            nodeType = inheritType(nodeClass, "value", nodeType);
-        }
-
-        if (nodeType == null) {
+        List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType);
+        if (!Utils.isAssignable(context, templateType.asType(), context.getTruffleTypes().getNode())) {
             return null;
         }
 
-        Elements elementUtil = context.getEnvironment().getElementUtils();
-        Set<Element> elementSet = new HashSet<>(elementUtil.getAllMembers(templateType));
-        if (!Utils.typeEquals(templateType.asType(), nodeType)) {
-            elementSet.addAll(elementUtil.getAllMembers(Utils.fromTypeMirror(nodeType)));
-
-            List<TypeElement> nodeLookupTypes = findSuperClasses(new ArrayList<TypeElement>(), Utils.fromTypeMirror(nodeType));
-            Collections.reverse(nodeLookupTypes);
-            lookupTypes.addAll(nodeLookupTypes);
+        List<? extends Element> elements = context.getEnvironment().getElementUtils().getAllMembers(templateType);
 
-            Set<TypeElement> types = new HashSet<>();
-            for (ListIterator<TypeElement> iterator = lookupTypes.listIterator(); iterator.hasNext();) {
-                TypeElement typeElement = iterator.next();
-                if (types.contains(typeElement)) {
-                    iterator.remove();
-                } else {
-                    types.add(typeElement);
-                }
-            }
-        }
-        List<Element> elements = new ArrayList<>(elementSet);
-
-        NodeData node = parseNodeData(templateType, nodeType, elements, lookupTypes);
-
+        NodeData node = parseNodeData(templateType, elements, lookupTypes);
         if (node.hasErrors()) {
             return node; // error sync point
         }
 
-        parseMethods(node, elements);
+        initializeChildren(node);
+
+        node.getSpecializations().addAll(new SpecializationMethodParser(context, node).parse(elements));
+        node.getSpecializations().addAll(new GenericParser(context, node).parse(elements));
+        node.getCasts().addAll(new CreateCastParser(context, node).parse(elements));
+        node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(elements));
 
         if (node.hasErrors()) {
-            return node;
-        }
-
-        List<NodeData> nodes;
-
-        if (node.isNodeContainer()) {
-            nodes = splitNodeData(node);
-        } else {
-            nodes = new ArrayList<>();
-            nodes.add(node);
+            return node;  // error sync point
         }
 
-        for (NodeData splittedNode : nodes) {
-            if (templateType.getModifiers().contains(Modifier.PRIVATE) && splittedNode.getSpecializations().size() > 0) {
-                splittedNode.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName());
-            }
+        verifySpecializationSameLength(node);
+        initializeSpecializations(elements, node);
+        initializeShortCircuits(node); // requires specializations and polymorphic specializations
 
-            finalizeSpecializations(elements, splittedNode);
-            verifyNode(splittedNode, elements);
-            expandExecutableTypeVarArgs(splittedNode);
-            createPolymorphicSpecializations(splittedNode);
-            assignShortCircuitsToSpecializations(splittedNode);
-        }
-
-        if (node.isNodeContainer()) {
-            node.setDeclaredNodes(nodes);
-            node.setSpecializationListeners(new ArrayList<SpecializationListenerData>());
-            node.setSpecializations(new ArrayList<SpecializationData>());
-        }
+        verifyVisibilities(node);
+        verifySpecializationOrder(node);
+        verifyMissingAbstractMethods(node, elements);
+        verifyConstructors(node);
+        verifyNamingConvention(node.getShortCircuits(), "needs");
+        verifySpecializationThrows(node);
         return node;
     }
 
-    private static void expandExecutableTypeVarArgs(NodeData node) {
-        for (ExecutableTypeData executableMethod : node.getExecutableTypes()) {
-            if (!(executableMethod.getMethod().isVarArgs() && executableMethod.getSpecification().isVariableRequiredArguments())) {
-                continue;
-            }
-            int expandArguments = node.getSignatureSize() - executableMethod.getSignatureSize();
-            if (expandArguments > 0) {
-                int signatureSize = executableMethod.getSignatureSize();
-                ActualParameter parameter = executableMethod.getSignatureParameter(signatureSize - 1);
-                for (int i = 0; i < expandArguments; i++) {
-                    int newVarArgsIndex = parameter.getVarArgsIndex() + i + 1;
-                    int newSpecificationIndex = parameter.getSpecificationIndex() + i + 1;
-                    executableMethod.getParameters().add(
-                                    new ActualParameter(parameter.getSpecification(), parameter.getTypeSystemType(), newSpecificationIndex, newVarArgsIndex, parameter.isImplicit()));
-                }
-
-            }
-        }
-    }
-
-    private void createPolymorphicSpecializations(NodeData node) {
-        if (!node.needsRewrites(context) || !node.isPolymorphic()) {
-            node.setPolymorphicSpecializations(Collections.<SpecializationData> emptyList());
-            return;
-        }
-
-        SpecializationData generic = node.getGenericSpecialization();
-
-        List<TypeData> polymorphicSignature = new ArrayList<>();
-        // TODO we should support more optimized for boxing
-        // List<ActualParameter> updatePolymorphic = generic.getReturnTypeAndParameters();
-        List<ActualParameter> updatePolymorphic = Arrays.asList();
-        for (ActualParameter genericParameter : updatePolymorphic) {
-            if (!genericParameter.getSpecification().isSignature()) {
-                continue;
-            }
-
-            Set<TypeData> usedTypes = new HashSet<>();
-            for (SpecializationData specialization : node.getSpecializations()) {
-                if (!specialization.isSpecialized()) {
-                    continue;
-                }
-                ActualParameter parameter = specialization.findParameter(genericParameter.getLocalName());
-                if (parameter == null) {
-                    throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName());
-                }
-                usedTypes.add(parameter.getTypeSystemType());
-            }
-
-            TypeData polymorphicType;
-            if (usedTypes.size() == 1) {
-                polymorphicType = usedTypes.iterator().next();
-            } else {
-                polymorphicType = node.getTypeSystem().getGenericTypeData();
-            }
-            polymorphicSignature.add(polymorphicType);
-        }
-
-        SpecializationData specialization = new SpecializationData(generic, false, false, true);
-        specialization.updateSignature(new Signature(polymorphicSignature));
-        specialization.setNode(node);
-        node.setGenericPolymorphicSpecialization(specialization);
-        // TODO remove polymoprhic specializations
-        node.setPolymorphicSpecializations(Collections.<SpecializationData> emptyList());
-    }
-
-    private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List<? extends Element> elements, List<TypeElement> typeHierarchy) {
-        NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString());
-
+    private NodeData parseNodeData(TypeElement templateType, List<? extends Element> elements, List<TypeElement> typeHierarchy) {
         AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class);
         if (typeSystemMirror == null) {
-            nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(nodeType));
+            NodeData nodeData = new NodeData(templateType);
+            nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(templateType));
             return nodeData;
         }
 
-        TypeMirror typeSytemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value");
-        final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true);
+        TypeMirror typeSystemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value");
+        final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true);
         if (typeSystem == null) {
-            nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSytemType));
+            NodeData nodeData = new NodeData(templateType);
+            nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSystemType));
             return nodeData;
         }
 
         AnnotationMirror polymorphicMirror = findFirstAnnotation(typeHierarchy, PolymorphicLimit.class);
+        int polymorphicLimit = -1;
         if (polymorphicMirror != null) {
             AnnotationValue limitValue = Utils.getAnnotationValue(polymorphicMirror, "value");
-            int polymorphicLimit = Utils.getAnnotationValue(Integer.class, polymorphicMirror, "value");
-            if (polymorphicLimit < 1) {
+            int customPolymorphicLimit = Utils.getAnnotationValue(Integer.class, polymorphicMirror, "value");
+            if (customPolymorphicLimit < 1) {
+                NodeData nodeData = new NodeData(templateType);
                 nodeData.addError(limitValue, "Invalid polymorphic limit %s.", polymorphicLimit);
+                return nodeData;
             }
-            nodeData.setPolymorphicDepth(polymorphicLimit);
+            polymorphicLimit = customPolymorphicLimit;
         }
 
         List<String> assumptionsList = new ArrayList<>();
@@ -325,22 +217,19 @@
             }
         }
         AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class);
+        String shortName = null;
         if (nodeInfoMirror != null) {
-            nodeData.setShortName(Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"));
+            shortName = Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName");
         }
 
-        nodeData.setAssumptions(new ArrayList<>(assumptionsList));
-        nodeData.setNodeType(nodeType);
-        AnnotationMirror nodeContainer = findFirstAnnotation(typeHierarchy, NodeContainer.class);
-        nodeData.setNodeContainer(nodeContainer != null);
-        nodeData.setTypeSystem(typeSystem);
-        nodeData.setFields(parseFields(typeHierarchy, elements));
-        nodeData.setChildren(parseChildren(nodeData, elements, typeHierarchy));
+        List<NodeFieldData> fields = parseFields(typeHierarchy, elements);
+        List<NodeChildData> children = parseChildren(elements, typeHierarchy);
+        List<NodeExecutionData> executions = parseExecutions(children, elements);
+
+        NodeData nodeData = new NodeData(templateType, shortName, typeSystem, children, executions, fields, assumptionsList, polymorphicLimit);
         nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
 
-        // resolveChildren invokes cyclic parsing.
         parsedNodes.put(Utils.getQualifiedName(templateType), nodeData);
-        resolveChildren(nodeData);
 
         return nodeData;
     }
@@ -389,28 +278,7 @@
         return fields;
     }
 
-    private void resolveChildren(NodeData node) {
-        for (NodeChildData nodeChild : node.getChildren()) {
-            NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(nodeChild.getNodeType()));
-            nodeChild.setNode(fieldNodeData);
-            if (fieldNodeData == null) {
-                nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(nodeChild.getNodeType()));
-            } else if (!Utils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) {
-                nodeChild.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(),
-                                NodeChild.class.getSimpleName(), Utils.getSimpleName(node.getTypeSystem().getTemplateType()), Utils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType()));
-            }
-            if (fieldNodeData != null) {
-                List<ExecutableTypeData> types = nodeChild.findGenericExecutableTypes(context);
-                if (types.isEmpty()) {
-                    AnnotationValue executeWithValue = Utils.getAnnotationValue(nodeChild.getMessageAnnotation(), "executeWith");
-                    nodeChild.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", nodeChild.getExecuteWith().size(),
-                                    Utils.getSimpleName(nodeChild.getNodeType()));
-                }
-            }
-        }
-    }
-
-    private List<NodeChildData> parseChildren(NodeData parent, List<? extends Element> elements, final List<TypeElement> typeHierarchy) {
+    private List<NodeChildData> parseChildren(List<? extends Element> elements, final List<TypeElement> typeHierarchy) {
         Set<String> shortCircuits = new HashSet<>();
         for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
             AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
@@ -435,7 +303,6 @@
         List<TypeElement> typeHierarchyReversed = new ArrayList<>(typeHierarchy);
         Collections.reverse(typeHierarchyReversed);
         for (TypeElement type : typeHierarchyReversed) {
-            AnnotationMirror nodeClassMirror = Utils.findAnnotationMirror(processingEnv, type, NodeContainer.class);
             AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, type, NodeChildren.class);
 
             TypeMirror nodeClassType = type.getSuperclass();
@@ -443,10 +310,6 @@
                 nodeClassType = null;
             }
 
-            if (nodeClassMirror != null) {
-                nodeClassType = inheritType(nodeClassMirror, "value", nodeClassType);
-            }
-
             List<AnnotationMirror> children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class);
             int index = 0;
             for (AnnotationMirror childMirror : children) {
@@ -470,16 +333,13 @@
 
                 Element getter = findGetter(elements, name, childType);
 
-                ExecutionKind kind = ExecutionKind.DEFAULT;
-                if (shortCircuits.contains(name)) {
-                    kind = ExecutionKind.SHORT_CIRCUIT;
-                }
-
-                NodeChildData nodeChild = new NodeChildData(parent, type, childMirror, name, childType, originalChildType, getter, cardinality, kind);
+                NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality);
 
                 parsedChildren.add(nodeChild);
 
-                verifyNodeChild(nodeChild);
+                if (nodeChild.getNodeType() == null) {
+                    nodeChild.addError("No valid node type could be resoleved.");
+                }
                 if (nodeChild.hasErrors()) {
                     continue;
                 }
@@ -541,153 +401,182 @@
         return filteredChildren;
     }
 
-    private void parseMethods(final NodeData node, List<Element> elements) {
-        node.setShortCircuits(new ShortCircuitParser(context, node).parse(elements));
-        node.setSpecializationListeners(new SpecializationListenerParser(context, node).parse(elements));
-        List<SpecializationData> generics = new GenericParser(context, node).parse(elements);
-        List<SpecializationData> specializations = new SpecializationMethodParser(context, node).parse(elements);
-        node.setCasts(new CreateCastParser(context, node).parse(elements));
+    private List<NodeExecutionData> parseExecutions(List<NodeChildData> children, List<? extends Element> elements) {
+        if (children == null) {
+            return null;
+        }
+
+        // pre-parse short circuits
+        Set<String> shortCircuits = new HashSet<>();
+        List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
+        for (ExecutableElement method : methods) {
+            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
+            if (mirror != null) {
+                shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value"));
+            }
+        }
+
+        boolean hasVarArgs = false;
+        int maxSignatureSize = 0;
+        if (!children.isEmpty()) {
+            int lastIndex = children.size() - 1;
+            hasVarArgs = children.get(lastIndex).getCardinality() == Cardinality.MANY;
+            if (hasVarArgs) {
+                maxSignatureSize = lastIndex;
+            } else {
+                maxSignatureSize = children.size();
+            }
+        }
+
+        // pre-parse specializations
+        for (ExecutableElement method : methods) {
+            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, Specialization.class);
+            if (mirror == null) {
+                continue;
+            }
 
-        List<SpecializationData> allSpecializations = new ArrayList<>();
-        allSpecializations.addAll(generics);
-        allSpecializations.addAll(specializations);
+            int currentArgumentCount = 0;
+            boolean skipShortCircuit = false;
+            for (VariableElement var : method.getParameters()) {
+                TypeMirror type = var.asType();
+                if (currentArgumentCount == 0) {
+                    // skip optionals
+                    if (Utils.typeEquals(type, context.getTruffleTypes().getFrame())) {
+                        continue;
+                    }
+                    // TODO skip optional fields?
+                }
+                int childIndex = currentArgumentCount < children.size() ? currentArgumentCount : children.size() - 1;
+                if (childIndex == -1) {
+                    continue;
+                }
+                if (!skipShortCircuit) {
+                    NodeChildData child = children.get(childIndex);
+                    if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentCount - childIndex))) {
+                        skipShortCircuit = true;
+                        continue;
+                    }
+                } else {
+                    skipShortCircuit = false;
+                }
 
-        node.setSpecializations(allSpecializations);
+                currentArgumentCount++;
+            }
+            maxSignatureSize = Math.max(maxSignatureSize, currentArgumentCount);
+        }
+
+        List<NodeExecutionData> executions = new ArrayList<>();
+        for (int i = 0; i < maxSignatureSize; i++) {
+            int childIndex = i;
+            boolean varArg = false;
+            if (childIndex >= children.size() - 1) {
+                if (hasVarArgs) {
+                    childIndex = children.size() - 1;
+                    varArg = hasVarArgs;
+                } else if (childIndex >= children.size()) {
+                    break;
+                }
+            }
+            int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1;
+            NodeChildData child = children.get(childIndex);
+            boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, varArgsIndex));
+            executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit));
+        }
+        return executions;
     }
 
-    private static List<NodeData> splitNodeData(NodeData node) {
-        SortedMap<String, List<SpecializationData>> groupedSpecializations = groupByNodeId(node.getSpecializations());
-        SortedMap<String, List<SpecializationListenerData>> groupedListeners = groupByNodeId(node.getSpecializationListeners());
-        SortedMap<String, List<CreateCastData>> groupedCasts = groupByNodeId(node.getCasts());
-
-        Set<String> ids = new TreeSet<>();
-        ids.addAll(groupedSpecializations.keySet());
-        ids.addAll(groupedListeners.keySet());
+    private static Map<Integer, List<ExecutableTypeData>> groupExecutableTypes(List<ExecutableTypeData> executableTypes) {
+        Map<Integer, List<ExecutableTypeData>> groupedTypes = new TreeMap<>();
+        for (ExecutableTypeData type : executableTypes) {
+            int evaluatedCount = type.getEvaluatedCount();
 
-        List<NodeData> splitted = new ArrayList<>();
-        for (String id : ids) {
-            List<SpecializationData> specializations = groupedSpecializations.get(id);
-            List<SpecializationListenerData> listeners = groupedListeners.get(id);
-            List<CreateCastData> casts = groupedCasts.get(id);
-
-            if (specializations == null) {
-                specializations = new ArrayList<>();
+            List<ExecutableTypeData> types = groupedTypes.get(evaluatedCount);
+            if (types == null) {
+                types = new ArrayList<>();
+                groupedTypes.put(evaluatedCount, types);
             }
-
-            if (listeners == null) {
-                listeners = new ArrayList<>();
-            }
-
-            String nodeId = node.getNodeId();
-            if (nodeId.endsWith("Node") && !nodeId.equals("Node")) {
-                nodeId = nodeId.substring(0, nodeId.length() - 4);
-            }
-            String newNodeId = nodeId + Utils.firstLetterUpperCase(id);
-            NodeData copy = new NodeData(node, id, newNodeId);
-
-            copy.setSpecializations(specializations);
-            copy.setSpecializationListeners(listeners);
-            copy.setCasts(casts);
-
-            splitted.add(copy);
+            types.add(type);
         }
 
-        node.setSpecializations(new ArrayList<SpecializationData>());
-        node.setSpecializationListeners(new ArrayList<SpecializationListenerData>());
-        node.setCasts(new ArrayList<CreateCastData>());
-
-        return splitted;
+        for (List<ExecutableTypeData> types : groupedTypes.values()) {
+            Collections.sort(types);
+        }
+        return groupedTypes;
     }
 
-    private void finalizeSpecializations(List<Element> elements, final NodeData node) {
-        List<SpecializationData> specializations = new ArrayList<>(node.getSpecializations());
+    private void initializeChildren(NodeData node) {
+        for (NodeChildData nodeChild : node.getChildren()) {
+            NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(nodeChild.getNodeType()));
+            nodeChild.setNode(fieldNodeData);
+            if (fieldNodeData == null) {
+                nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(nodeChild.getNodeType()));
+            } else if (!Utils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) {
+                nodeChild.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(),
+                                NodeChild.class.getSimpleName(), Utils.getSimpleName(node.getTypeSystem().getTemplateType()), Utils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType()));
+            }
+            if (fieldNodeData != null) {
+                List<ExecutableTypeData> types = nodeChild.findGenericExecutableTypes(context);
+                if (types.isEmpty()) {
+                    AnnotationValue executeWithValue = Utils.getAnnotationValue(nodeChild.getMessageAnnotation(), "executeWith");
+                    nodeChild.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", nodeChild.getExecuteWith().size(),
+                                    Utils.getSimpleName(nodeChild.getNodeType()));
+                }
+            }
+        }
+    }
 
-        if (specializations.isEmpty()) {
+    private void initializeSpecializations(List<? extends Element> elements, final NodeData node) {
+        if (node.getSpecializations().isEmpty()) {
             return;
         }
 
-        for (SpecializationData specialization : specializations) {
-            matchGuards(elements, specialization);
-        }
-
-        List<SpecializationData> generics = new ArrayList<>();
-        for (SpecializationData spec : specializations) {
-            if (spec.isGeneric()) {
-                generics.add(spec);
+        for (SpecializationData specialization : node.getSpecializations()) {
+            if (!specialization.isSpecialized()) {
+                continue;
             }
-        }
-
-        if (generics.size() == 1 && specializations.size() == 1) {
-            for (SpecializationData generic : generics) {
-                generic.addError("@%s defined but no @%s.", Generic.class.getSimpleName(), Specialization.class.getSimpleName());
-            }
-        }
-
-        SpecializationData genericSpecialization = null;
-        if (generics.size() > 1) {
-            for (SpecializationData generic : generics) {
-                generic.addError("Only @%s is allowed per operation.", Generic.class.getSimpleName());
-            }
-            return;
-        } else if (generics.size() == 1) {
-            genericSpecialization = generics.get(0);
-        } else if (node.needsRewrites(context)) {
-            genericSpecialization = createGenericSpecialization(node, specializations);
-            specializations.add(genericSpecialization);
+            initializeGuards(elements, specialization);
         }
 
-        if (genericSpecialization != null) {
-            for (ActualParameter parameter : genericSpecialization.getReturnTypeAndParameters()) {
-                if (Utils.isObject(parameter.getType())) {
-                    continue;
-                }
-                Set<String> types = new HashSet<>();
-                for (SpecializationData specialization : specializations) {
-                    ActualParameter actualParameter = specialization.findParameter(parameter.getLocalName());
-                    if (actualParameter != null) {
-                        types.add(Utils.getQualifiedName(actualParameter.getType()));
-                    }
-                }
-                if (types.size() > 1) {
-                    genericSpecialization.replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, node.getTypeSystem().getGenericTypeData()));
-                }
-            }
-            TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", node, genericSpecialization.getSpecification(), null, null, genericSpecialization.getReturnType(),
-                            genericSpecialization.getParameters());
-            // should not use messages from generic specialization
-            uninializedMethod.getMessages().clear();
-            specializations.add(new SpecializationData(uninializedMethod, false, true, false));
+        initializeGeneric(node);
+        initializeUninitialized(node);
+        initializePolymorphism(node); // requires specializations
+        Collections.sort(node.getSpecializations());
+        initializeReachability(node);
+
+        // reduce polymorphicness if generic is not reachable
+        if (node.getGenericSpecialization() != null && !node.getGenericSpecialization().isReachable()) {
+            node.setPolymorphicDepth(1);
+            node.getSpecializations().remove(node.getPolymorphicSpecialization());
         }
 
-        Collections.sort(specializations);
-
-        node.setSpecializations(specializations);
-
         List<SpecializationData> needsId = new ArrayList<>();
-        for (SpecializationData specialization : specializations) {
+        for (SpecializationData specialization : node.getSpecializations()) {
             if (specialization.isGeneric()) {
                 specialization.setId("Generic");
             } else if (specialization.isUninitialized()) {
                 specialization.setId("Uninitialized");
+            } else if (specialization.isPolymorphic()) {
+                specialization.setId("Polymorphic");
+            } else if (specialization.isSpecialized()) {
+                needsId.add(specialization);
             } else {
-                needsId.add(specialization);
+                throw new AssertionError();
             }
         }
 
         // verify specialization parameter length
-        if (verifySpecializationParameters(node)) {
-            List<String> ids = calculateSpecializationIds(needsId);
-            for (int i = 0; i < ids.size(); i++) {
-                needsId.get(i).setId(ids.get(i));
-            }
+        List<String> ids = initializeSpecializationIds(needsId);
+        for (int i = 0; i < ids.size(); i++) {
+            needsId.get(i).setId(ids.get(i));
         }
 
-        // calculate reachability
+    }
+
+    private void initializeReachability(final NodeData node) {
         SpecializationData prev = null;
-        int polymorphicCombinations = 0;
         boolean reachable = true;
-        for (SpecializationData specialization : specializations) {
-            if (specialization.isUninitialized()) {
+        for (SpecializationData specialization : node.getSpecializations()) {
+            if (specialization.isUninitialized() || specialization.isPolymorphic()) {
                 specialization.setReachable(true);
                 continue;
             }
@@ -700,204 +589,21 @@
             if (!specialization.hasRewrite(context)) {
                 reachable = false;
             }
-            if (!specialization.isGeneric()) {
-                int combinations = 1;
-                for (ActualParameter parameter : specialization.getParameters()) {
-                    if (!parameter.getSpecification().isSignature()) {
-                        continue;
-                    }
-                    TypeData type = parameter.getTypeSystemType();
-                    combinations *= node.getTypeSystem().lookupSourceTypes(type).size();
-                }
-                polymorphicCombinations += combinations;
-            }
-
             prev = specialization;
         }
-
-        // initialize polymorphic depth
-        if (node.getPolymorphicDepth() < 0) {
-            node.setPolymorphicDepth(polymorphicCombinations - 1);
-        }
-
-        // reduce polymorphicness if generic is not reachable
-        if (node.getGenericSpecialization() != null && !node.getGenericSpecialization().isReachable()) {
-            node.setPolymorphicDepth(1);
-        }
     }
 
-    private SpecializationData createGenericSpecialization(final NodeData node, List<SpecializationData> specializations) {
-        SpecializationData genericSpecialization;
-        SpecializationData specialization = specializations.get(0);
-        GenericParser parser = new GenericParser(context, node);
-        MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null);
-
-        List<ActualParameter> parameters = new ArrayList<>();
-        for (ActualParameter parameter : specialization.getReturnTypeAndParameters()) {
-            if (!parameter.getSpecification().isSignature()) {
-                parameters.add(new ActualParameter(parameter));
-                continue;
-            }
-            NodeData childNode = node;
-            NodeChildData child = node.findChild(parameter.getSpecification().getName());
-            if (child != null) {
-                childNode = child.getNodeData();
-            }
-
-            TypeData genericType = null;
-
-            Set<TypeData> types = new HashSet<>();
-            for (SpecializationData otherSpecialization : specializations) {
-                ActualParameter otherParameter = otherSpecialization.findParameter(parameter.getLocalName());
-                if (otherParameter != null) {
-                    types.add(otherParameter.getTypeSystemType());
-                }
-            }
-
-            assert !types.isEmpty();
-
-            if (types.size() == 1) {
-                ExecutableTypeData executable = childNode.findExecutableType(types.iterator().next(), 0);
-                if (executable != null && !executable.hasUnexpectedValue(context)) {
-                    genericType = types.iterator().next();
-                } else {
-                    genericType = childNode.findAnyGenericExecutableType(context, 0).getType();
-                }
-            } else {
-                genericType = childNode.findAnyGenericExecutableType(context, 0).getType();
-            }
-
-            parameters.add(new ActualParameter(parameter, genericType));
-        }
-        ActualParameter returnType = parameters.get(0);
-        parameters = parameters.subList(1, parameters.size());
-
-        TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters);
-        genericSpecialization = new SpecializationData(genericMethod, true, false, false);
-        return genericSpecialization;
-    }
-
-    private void assignShortCircuitsToSpecializations(NodeData node) {
-        Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
-
-        boolean valid = true;
-        for (NodeChildData field : node.filterFields(ExecutionKind.SHORT_CIRCUIT)) {
-            String valueName = field.getName();
-            List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
-
-            if (availableCircuits == null || availableCircuits.isEmpty()) {
-                node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
-                valid = false;
-                continue;
-            }
-
-            boolean sameMethodName = true;
-            String methodName = availableCircuits.get(0).getMethodName();
-            for (ShortCircuitData circuit : availableCircuits) {
-                if (!circuit.getMethodName().equals(methodName)) {
-                    sameMethodName = false;
-                }
-            }
-
-            if (!sameMethodName) {
-                for (ShortCircuitData circuit : availableCircuits) {
-                    circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName);
-                }
-                valid = false;
-                continue;
-            }
-
-            ShortCircuitData genericCircuit = null;
-            for (ShortCircuitData circuit : availableCircuits) {
-                if (isGenericShortCutMethod(node, circuit)) {
-                    genericCircuit = circuit;
-                    break;
-                }
-            }
-
-            if (genericCircuit == null) {
-                node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
-                valid = false;
-                continue;
-            }
-
-            for (ShortCircuitData circuit : availableCircuits) {
-                if (circuit != genericCircuit) {
-                    circuit.setGenericShortCircuitMethod(genericCircuit);
-                }
-            }
-        }
-
-        if (!valid) {
-            return;
-        }
-
-        NodeChildData[] fields = node.filterFields(ExecutionKind.SHORT_CIRCUIT);
-        List<SpecializationData> specializations = new ArrayList<>();
-        specializations.addAll(node.getSpecializations());
-        specializations.addAll(node.getPolymorphicSpecializations());
-
-        for (SpecializationData specialization : specializations) {
-            List<ShortCircuitData> assignedShortCuts = new ArrayList<>(fields.length);
-
-            for (int i = 0; i < fields.length; i++) {
-                List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(fields[i].getName());
-
-                ShortCircuitData genericShortCircuit = null;
-                ShortCircuitData compatibleShortCircuit = null;
-                for (ShortCircuitData circuit : availableShortCuts) {
-                    if (circuit.isGeneric()) {
-                        genericShortCircuit = circuit;
-                    } else if (circuit.isCompatibleTo(specialization)) {
-                        compatibleShortCircuit = circuit;
-                    }
-                }
-
-                if (compatibleShortCircuit == null) {
-                    compatibleShortCircuit = genericShortCircuit;
-                }
-                assignedShortCuts.add(compatibleShortCircuit);
-            }
-            specialization.setShortCircuits(assignedShortCuts);
-        }
-    }
-
-    private void matchGuards(List<Element> elements, SpecializationData specialization) {
-        if (specialization.getGuardDefinitions().isEmpty()) {
-            specialization.setGuards(Collections.<GuardData> emptyList());
-            return;
-        }
-
-        List<GuardData> foundGuards = new ArrayList<>();
-        List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
-        for (String guardDefinition : specialization.getGuardDefinitions()) {
-            GuardParser parser = new GuardParser(context, specialization, guardDefinition);
-            List<GuardData> guards = parser.parse(methods);
-            if (!guards.isEmpty()) {
-                foundGuards.add(guards.get(0));
-            } else {
-                // error no guard found
-                MethodSpec spec = parser.createSpecification(specialization.getMethod(), null);
-                spec.applyTypeDefinitions("types");
-                specialization.addError("Guard with method name '%s' not found. Expected signature: %n%s", guardDefinition, spec.toSignatureString("guard"));
-            }
-        }
-
-        specialization.setGuards(foundGuards);
-
-    }
-
-    private static List<String> calculateSpecializationIds(List<SpecializationData> specializations) {
+    private static List<String> initializeSpecializationIds(List<SpecializationData> specializations) {
         int lastSize = -1;
         List<List<String>> signatureChunks = new ArrayList<>();
         for (SpecializationData other : specializations) {
-            if (other.isUninitialized() || other.isGeneric()) {
+            if (!other.isSpecialized()) {
                 continue;
             }
             List<String> paramIds = new LinkedList<>();
             paramIds.add(Utils.getTypeId(other.getReturnType().getType()));
             for (ActualParameter param : other.getParameters()) {
-                if (other.getNode().findChild(param.getSpecification().getName()) == null) {
+                if (param.getSpecification().getExecution() == null) {
                     continue;
                 }
                 paramIds.add(Utils.getTypeId(param.getType()));
@@ -999,25 +705,373 @@
         return signatures;
     }
 
-    private void verifyNode(NodeData nodeData, List<? extends Element> elements) {
-        // verify order is not ambiguous
-        verifySpecializationOrder(nodeData);
+    private void initializeGuards(List<? extends Element> elements, SpecializationData specialization) {
+        if (specialization.getGuardDefinitions().isEmpty()) {
+            specialization.setGuards(Collections.<GuardData> emptyList());
+            return;
+        }
+
+        List<GuardData> foundGuards = new ArrayList<>();
+        List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
+        for (String guardDefinition : specialization.getGuardDefinitions()) {
+            GuardParser parser = new GuardParser(context, specialization, guardDefinition);
+            List<GuardData> guards = parser.parse(methods);
+            if (!guards.isEmpty()) {
+                foundGuards.add(guards.get(0));
+            } else {
+                // error no guard found
+                MethodSpec spec = parser.createSpecification(specialization.getMethod(), null);
+                spec.applyTypeDefinitions("types");
+                specialization.addError("Guard with method name '%s' not found. Expected signature: %n%s", guardDefinition, spec.toSignatureString("guard"));
+            }
+        }
+
+        specialization.setGuards(foundGuards);
+
+    }
+
+    private void initializeGeneric(final NodeData node) {
+        if (!node.needsRewrites(context)) {
+            return;
+        }
+
+        List<SpecializationData> generics = new ArrayList<>();
+        for (SpecializationData spec : node.getSpecializations()) {
+            if (spec.isGeneric()) {
+                generics.add(spec);
+            }
+        }
 
-        verifyMissingAbstractMethods(nodeData, elements);
+        if (generics.size() == 1 && node.getSpecializations().size() == 1) {
+            // TODO this limitation should be lifted
+            for (SpecializationData generic : generics) {
+                generic.addError("@%s defined but no @%s.", Generic.class.getSimpleName(), Specialization.class.getSimpleName());
+            }
+        }
+
+        if (generics.isEmpty()) {
+            node.getSpecializations().add(createGenericSpecialization(node));
+        } else {
+            if (generics.size() > 1) {
+                for (SpecializationData generic : generics) {
+                    generic.addError("Only @%s is allowed per operation.", Generic.class.getSimpleName());
+                }
+            }
+        }
+    }
+
+    private SpecializationData createGenericSpecialization(final NodeData node) {
+        GenericParser parser = new GenericParser(context, node);
+        MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null);
+
+        List<TypeMirror> parameterTypes = new ArrayList<>();
+        int signatureIndex = 1;
+        for (ParameterSpec spec : specification.getRequired()) {
+            parameterTypes.add(createGenericType(spec, node.getSpecializations(), signatureIndex));
+            if (spec.isSignature()) {
+                signatureIndex++;
+            }
+        }
+
+        TypeMirror returnType = createGenericType(specification.getReturnType(), node.getSpecializations(), 0);
+        SpecializationData generic = parser.create("Generic", null, null, returnType, parameterTypes);
+        if (generic == null) {
+            throw new RuntimeException("Unable to create generic signature for node " + node.getNodeId() + " with " + parameterTypes + ". Specification " + specification + ".");
+        }
+
+        return generic;
+    }
 
-        verifyConstructors(nodeData);
+    private TypeMirror createGenericType(ParameterSpec spec, List<SpecializationData> specializations, int signatureIndex) {
+        NodeExecutionData execution = spec.getExecution();
+        if (execution == null) {
+            if (spec.getAllowedTypes().size() == 1) {
+                return spec.getAllowedTypes().get(0);
+            } else {
+                return Utils.getCommonSuperType(context, spec.getAllowedTypes().toArray(new TypeMirror[0]));
+            }
+        } else {
+            Set<TypeData> types = new HashSet<>();
+            for (SpecializationData specialization : specializations) {
+                types.add(specialization.getTypeSignature().get(signatureIndex));
+            }
+
+            NodeChildData child = execution.getChild();
+            TypeData genericType = null;
+            if (types.size() == 1) {
+                ExecutableTypeData executable = child.findExecutableType(context, types.iterator().next());
+                if (executable != null && (signatureIndex == 0 || !executable.hasUnexpectedValue(context))) {
+                    genericType = types.iterator().next();
+                }
+            }
+            if (genericType == null) {
+                genericType = child.findAnyGenericExecutableType(context).getType();
+            }
+            return genericType.getPrimitiveType();
+        }
+    }
 
-        verifyNamingConvention(nodeData.getShortCircuits(), "needs");
+    private static void initializeUninitialized(final NodeData node) {
+        SpecializationData generic = node.getGenericSpecialization();
+        if (generic == null) {
+            return;
+        }
+        for (ActualParameter parameter : generic.getReturnTypeAndParameters()) {
+            if (Utils.isObject(parameter.getType())) {
+                continue;
+            }
+            Set<String> types = new HashSet<>();
+            for (SpecializationData specialization : node.getSpecializations()) {
+                ActualParameter actualParameter = specialization.findParameter(parameter.getLocalName());
+                if (actualParameter != null) {
+                    types.add(Utils.getQualifiedName(actualParameter.getType()));
+                }
+            }
+            if (types.size() > 1) {
+                generic.replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, node.getTypeSystem().getGenericTypeData()));
+            }
+        }
+        TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", node, generic.getSpecification(), null, null, generic.getReturnType(), generic.getParameters());
+        // should not use messages from generic specialization
+        uninializedMethod.getMessages().clear();
+        node.getSpecializations().add(new SpecializationData(node, uninializedMethod, SpecializationKind.UNINITIALIZED));
+    }
+
+    private void initializePolymorphism(NodeData node) {
+        initializePolymorphicDepth(node);
+
+        if (!node.needsRewrites(context) || !node.isPolymorphic()) {
+            return;
+        }
 
-        verifySpecializationThrows(nodeData);
+        SpecializationData generic = node.getGenericSpecialization();
+
+        List<TypeData> polymorphicSignature = new ArrayList<>();
+        List<ActualParameter> updatePolymorphic = Arrays.asList();
+        for (ActualParameter genericParameter : updatePolymorphic) {
+            if (!genericParameter.getSpecification().isSignature()) {
+                continue;
+            }
+
+            Set<TypeData> usedTypes = new HashSet<>();
+            for (SpecializationData specialization : node.getSpecializations()) {
+                if (!specialization.isSpecialized()) {
+                    continue;
+                }
+                ActualParameter parameter = specialization.findParameter(genericParameter.getLocalName());
+                if (parameter == null) {
+                    throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName());
+                }
+                usedTypes.add(parameter.getTypeSystemType());
+            }
+
+            TypeData polymorphicType;
+            if (usedTypes.size() == 1) {
+                polymorphicType = usedTypes.iterator().next();
+            } else {
+                polymorphicType = node.getTypeSystem().getGenericTypeData();
+            }
+            polymorphicSignature.add(polymorphicType);
+        }
+
+        SpecializationData polymorphic = new SpecializationData(node, generic, SpecializationKind.POLYMORPHIC);
+        polymorphic.updateSignature(new TypeSignature(polymorphicSignature));
+        node.getSpecializations().add(polymorphic);
     }
 
-    private static void verifyNodeChild(NodeChildData nodeChild) {
-        if (nodeChild.getNodeType() == null) {
-            nodeChild.addError("No valid node type could be resoleved.");
+    private static void initializePolymorphicDepth(final NodeData node) {
+        int polymorphicCombinations = 0;
+        for (SpecializationData specialization : node.getSpecializations()) {
+            if (specialization.isGeneric()) {
+                continue;
+            }
+
+            int combinations = 1;
+            for (ActualParameter parameter : specialization.getSignatureParameters()) {
+                combinations *= node.getTypeSystem().lookupSourceTypes(parameter.getTypeSystemType()).size();
+            }
+            polymorphicCombinations += combinations;
+        }
+
+        // initialize polymorphic depth
+        if (node.getPolymorphicDepth() < 0) {
+            node.setPolymorphicDepth(polymorphicCombinations - 1);
+        }
+
+    }
+
+    private void initializeShortCircuits(NodeData node) {
+        Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
+
+        boolean valid = true;
+        List<NodeExecutionData> shortCircuitExecutions = new ArrayList<>();
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (!execution.isShortCircuit()) {
+                continue;
+            }
+            shortCircuitExecutions.add(execution);
+            String valueName = execution.getShortCircuitId();
+            List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
+
+            if (availableCircuits == null || availableCircuits.isEmpty()) {
+                node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
+                valid = false;
+                continue;
+            }
+
+            boolean sameMethodName = true;
+            String methodName = availableCircuits.get(0).getMethodName();
+            for (ShortCircuitData circuit : availableCircuits) {
+                if (!circuit.getMethodName().equals(methodName)) {
+                    sameMethodName = false;
+                }
+            }
+
+            if (!sameMethodName) {
+                for (ShortCircuitData circuit : availableCircuits) {
+                    circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName);
+                }
+                valid = false;
+                continue;
+            }
+
+            ShortCircuitData genericCircuit = null;
+            for (ShortCircuitData circuit : availableCircuits) {
+                if (isGenericShortCutMethod(circuit)) {
+                    genericCircuit = circuit;
+                    break;
+                }
+            }
+
+            if (genericCircuit == null) {
+                node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
+                valid = false;
+                continue;
+            }
+
+            for (ShortCircuitData circuit : availableCircuits) {
+                if (circuit != genericCircuit) {
+                    circuit.setGenericShortCircuitMethod(genericCircuit);
+                }
+            }
+        }
+
+        if (!valid) {
+            return;
         }
-        // FIXME verify node child
-        // FIXME verify node type set
+
+        List<SpecializationData> specializations = new ArrayList<>();
+        specializations.addAll(node.getSpecializations());
+        for (SpecializationData specialization : specializations) {
+            List<ShortCircuitData> assignedShortCuts = new ArrayList<>(shortCircuitExecutions.size());
+
+            for (NodeExecutionData shortCircuit : shortCircuitExecutions) {
+                List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(shortCircuit.getShortCircuitId());
+
+                ShortCircuitData genericShortCircuit = null;
+                ShortCircuitData compatibleShortCircuit = null;
+                for (ShortCircuitData circuit : availableShortCuts) {
+                    if (circuit.isGeneric()) {
+                        genericShortCircuit = circuit;
+                    } else if (circuit.isCompatibleTo(specialization)) {
+                        compatibleShortCircuit = circuit;
+                    }
+                }
+
+                if (compatibleShortCircuit == null) {
+                    compatibleShortCircuit = genericShortCircuit;
+                }
+                assignedShortCuts.add(compatibleShortCircuit);
+            }
+            specialization.setShortCircuits(assignedShortCuts);
+        }
+    }
+
+    private boolean isGenericShortCutMethod(ShortCircuitData method) {
+        for (ActualParameter parameter : method.getParameters()) {
+            NodeExecutionData execution = parameter.getSpecification().getExecution();
+            if (execution == null) {
+                continue;
+            }
+            ExecutableTypeData found = null;
+            List<ExecutableTypeData> executableElements = execution.getChild().findGenericExecutableTypes(context);
+            for (ExecutableTypeData executable : executableElements) {
+                if (executable.getType().equalsType(parameter.getTypeSystemType())) {
+                    found = executable;
+                    break;
+                }
+            }
+            if (found == null) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static Map<String, List<ShortCircuitData>> groupShortCircuits(List<ShortCircuitData> shortCircuits) {
+        Map<String, List<ShortCircuitData>> group = new HashMap<>();
+        for (ShortCircuitData shortCircuit : shortCircuits) {
+            List<ShortCircuitData> circuits = group.get(shortCircuit.getValueName());
+            if (circuits == null) {
+                circuits = new ArrayList<>();
+                group.put(shortCircuit.getValueName(), circuits);
+            }
+            circuits.add(shortCircuit);
+        }
+        return group;
+    }
+
+    private static boolean verifySpecializationSameLength(NodeData nodeData) {
+        int lastArgs = -1;
+        for (SpecializationData specializationData : nodeData.getSpecializations()) {
+            int signatureArgs = specializationData.getSignatureSize();
+            if (lastArgs == signatureArgs) {
+                continue;
+            }
+            if (lastArgs != -1) {
+                for (SpecializationData specialization : nodeData.getSpecializations()) {
+                    specialization.addError("All specializations must have the same number of arguments.");
+                }
+                return false;
+            } else {
+                lastArgs = signatureArgs;
+            }
+        }
+        return true;
+    }
+
+    private static void verifyVisibilities(NodeData node) {
+        if (node.getTemplateType().getModifiers().contains(Modifier.PRIVATE) && node.getSpecializations().size() > 0) {
+            node.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName());
+        }
+    }
+
+    private static void verifySpecializationOrder(NodeData node) {
+        List<SpecializationData> specializations = node.getSpecializations();
+        for (int i = 0; i < specializations.size(); i++) {
+            SpecializationData m1 = specializations.get(i);
+            for (int j = i + 1; j < specializations.size(); j++) {
+                SpecializationData m2 = specializations.get(j);
+                int inferredOrder = m1.compareBySignature(m2);
+
+                if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
+                    int specOrder = m1.getOrder() - m2.getOrder();
+                    if (specOrder == 0) {
+                        m1.addError("Order value %d used multiple times", m1.getOrder());
+                        m2.addError("Order value %d used multiple times", m1.getOrder());
+                        return;
+                    } else if ((specOrder < 0 && inferredOrder > 0) || (specOrder > 0 && inferredOrder < 0)) {
+                        m1.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
+                        m2.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
+                        return;
+                    }
+                } else if (inferredOrder == 0) {
+                    SpecializationData m = (m1.getOrder() == Specialization.DEFAULT_ORDER ? m1 : m2);
+                    m.addError("Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this.");
+                    return;
+                }
+            }
+        }
     }
 
     private static void verifyMissingAbstractMethods(NodeData nodeData, List<? extends Element> originalElements) {
@@ -1028,7 +1082,6 @@
         }
 
         List<Element> elements = new ArrayList<>(originalElements);
-
         Set<Element> unusedElements = new HashSet<>(elements);
         for (TemplateMethod method : nodeData.getAllTemplateMethods()) {
             unusedElements.remove(method.getMethod());
@@ -1053,6 +1106,33 @@
         }
     }
 
+    private static void verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) {
+        for (int i = 0; i < methods.size(); i++) {
+            TemplateMethod m1 = methods.get(i);
+            if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
+                m1.addError("Naming convention: method name must start with '%s'.", prefix);
+            }
+        }
+    }
+
+    private static void verifySpecializationThrows(NodeData node) {
+        Map<String, SpecializationData> specializationMap = new HashMap<>();
+        for (SpecializationData spec : node.getSpecializations()) {
+            specializationMap.put(spec.getMethodName(), spec);
+        }
+        for (SpecializationData sourceSpecialization : node.getSpecializations()) {
+            if (sourceSpecialization.getExceptions() != null) {
+                for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) {
+                    for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) {
+                        if (otherThrowsData != throwsData && Utils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) {
+                            throwsData.addError("Duplicate exception type.");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     private void verifyConstructors(NodeData nodeData) {
         if (!nodeData.needsRewrites(context)) {
             // no specialization constructor is needed if the node never rewrites.
@@ -1093,104 +1173,6 @@
         return constructor.getParameters().size() == 1 && Utils.typeEquals(constructor.getParameters().get(0).asType(), context.getTruffleTypes().getSourceSection());
     }
 
-    private static boolean verifySpecializationParameters(NodeData nodeData) {
-        boolean valid = true;
-        int args = -1;
-        for (SpecializationData specializationData : nodeData.getSpecializations()) {
-            int signatureArgs = 0;
-            for (ActualParameter param : specializationData.getParameters()) {
-                if (param.getSpecification().isSignature()) {
-                    signatureArgs++;
-                }
-            }
-            if (args != -1 && args != signatureArgs) {
-                valid = false;
-                break;
-            }
-            args = signatureArgs;
-        }
-        if (!valid) {
-            for (SpecializationData specialization : nodeData.getSpecializations()) {
-                specialization.addError("All specializations must have the same number of arguments.");
-            }
-        }
-        return valid;
-    }
-
-    private static void verifySpecializationOrder(NodeData node) {
-        List<SpecializationData> specializations = node.getSpecializations();
-        for (int i = 0; i < specializations.size(); i++) {
-            SpecializationData m1 = specializations.get(i);
-            for (int j = i + 1; j < specializations.size(); j++) {
-                SpecializationData m2 = specializations.get(j);
-                int inferredOrder = m1.compareBySignature(m2);
-
-                if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
-                    int specOrder = m1.getOrder() - m2.getOrder();
-                    if (specOrder == 0) {
-                        m1.addError("Order value %d used multiple times", m1.getOrder());
-                        m2.addError("Order value %d used multiple times", m1.getOrder());
-                        return;
-                    } else if ((specOrder < 0 && inferredOrder > 0) || (specOrder > 0 && inferredOrder < 0)) {
-                        m1.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
-                        m2.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
-                        return;
-                    }
-                } else if (inferredOrder == 0) {
-                    SpecializationData m = (m1.getOrder() == Specialization.DEFAULT_ORDER ? m1 : m2);
-                    m.addError("Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this.");
-                    return;
-                }
-            }
-        }
-    }
-
-    private static void verifySpecializationThrows(NodeData node) {
-        Map<String, SpecializationData> specializationMap = new HashMap<>();
-        for (SpecializationData spec : node.getSpecializations()) {
-            specializationMap.put(spec.getMethodName(), spec);
-        }
-        for (SpecializationData sourceSpecialization : node.getSpecializations()) {
-            if (sourceSpecialization.getExceptions() != null) {
-                for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) {
-                    for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) {
-                        if (otherThrowsData != throwsData && Utils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) {
-                            throwsData.addError("Duplicate exception type.");
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private static void verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) {
-        for (int i = 0; i < methods.size(); i++) {
-            TemplateMethod m1 = methods.get(i);
-            if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
-                m1.addError("Naming convention: method name must start with '%s'.", prefix);
-            }
-        }
-    }
-
-    private static Map<Integer, List<ExecutableTypeData>> groupExecutableTypes(List<ExecutableTypeData> executableTypes) {
-        Map<Integer, List<ExecutableTypeData>> groupedTypes = new TreeMap<>();
-        for (ExecutableTypeData type : executableTypes) {
-            int evaluatedCount = type.getEvaluatedCount();
-
-            List<ExecutableTypeData> types = groupedTypes.get(evaluatedCount);
-            if (types == null) {
-                types = new ArrayList<>();
-                groupedTypes.put(evaluatedCount, types);
-            }
-            types.add(type);
-        }
-
-        for (List<ExecutableTypeData> types : groupedTypes.values()) {
-            Collections.sort(types);
-        }
-        return groupedTypes;
-    }
-
     private AnnotationMirror findFirstAnnotation(List<? extends Element> elements, Class<? extends Annotation> annotation) {
         for (Element element : elements) {
             AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, element, annotation);
@@ -1230,61 +1212,13 @@
         return null;
     }
 
-    private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) {
-        for (ActualParameter parameter : method.getParameters()) {
-            NodeChildData field = node.findChild(parameter.getSpecification().getName());
-            if (field == null) {
-                continue;
-            }
-            ExecutableTypeData found = null;
-            List<ExecutableTypeData> executableElements = field.findGenericExecutableTypes(context);
-            for (ExecutableTypeData executable : executableElements) {
-                if (executable.getType().equalsType(parameter.getTypeSystemType())) {
-                    found = executable;
-                    break;
-                }
-            }
-            if (found == null) {
-                return false;
+    private static List<TypeElement> collectSuperClasses(List<TypeElement> collection, TypeElement element) {
+        if (element != null) {
+            collection.add(element);
+            if (element.getSuperclass() != null) {
+                collectSuperClasses(collection, Utils.fromTypeMirror(element.getSuperclass()));
             }
         }
-        return true;
-    }
-
-    private static Map<String, List<ShortCircuitData>> groupShortCircuits(List<ShortCircuitData> shortCircuits) {
-        Map<String, List<ShortCircuitData>> group = new HashMap<>();
-        for (ShortCircuitData shortCircuit : shortCircuits) {
-            List<ShortCircuitData> circuits = group.get(shortCircuit.getValueName());
-            if (circuits == null) {
-                circuits = new ArrayList<>();
-                group.put(shortCircuit.getValueName(), circuits);
-            }
-            circuits.add(shortCircuit);
-        }
-        return group;
-    }
-
-    private static <M extends TemplateMethod> SortedMap<String, List<M>> groupByNodeId(List<M> methods) {
-        SortedMap<String, List<M>> grouped = new TreeMap<>();
-        for (M m : methods) {
-            List<M> list = grouped.get(m.getId());
-            if (list == null) {
-                list = new ArrayList<>();
-                grouped.put(m.getId(), list);
-            }
-            list.add(m);
-        }
-        return grouped;
-    }
-
-    private static List<TypeElement> findSuperClasses(List<TypeElement> collection, TypeElement element) {
-        if (element.getSuperclass() != null) {
-            TypeElement superElement = Utils.fromTypeMirror(element.getSuperclass());
-            if (superElement != null) {
-                findSuperClasses(collection, superElement);
-            }
-        }
-        collection.add(element);
         return collection;
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java	Tue Jan 07 22:36:23 2014 +0100
@@ -29,7 +29,6 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
 import com.oracle.truffle.dsl.processor.template.*;
 
 public class ShortCircuitParser extends NodeMethodParser<ShortCircuitData> {
@@ -40,15 +39,17 @@
         super(context, node);
 
         shortCircuitValues = new HashSet<>();
-        NodeChildData[] shortCircuitFields = node.filterFields(ExecutionKind.SHORT_CIRCUIT);
-        for (NodeChildData field : shortCircuitFields) {
-            shortCircuitValues.add(field.getName());
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (execution.isShortCircuit()) {
+                shortCircuitValues.add(execution.getShortCircuitId());
+            }
         }
     }
 
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
         String shortCircuitValue = Utils.getAnnotationValue(String.class, mirror, "value");
+
         return createDefaultMethodSpec(method, mirror, true, shortCircuitValue);
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java	Tue Jan 07 22:36:23 2014 +0100
@@ -33,24 +33,25 @@
 
 public class SpecializationData extends TemplateMethod {
 
+    public enum SpecializationKind {
+        UNINITIALIZED, SPECIALIZED, POLYMORPHIC, GENERIC
+    }
+
+    private final NodeData node;
     private final int order;
-    private final boolean generic;
-    private final boolean polymorphic;
-    private final boolean uninitialized;
+    private final SpecializationKind kind;
     private final List<SpecializationThrowsData> exceptions;
     private List<String> guardDefinitions = Collections.emptyList();
     private List<GuardData> guards = Collections.emptyList();
     private List<ShortCircuitData> shortCircuits;
     private List<String> assumptions = Collections.emptyList();
-    private NodeData node;
     private boolean reachable;
 
-    public SpecializationData(TemplateMethod template, int order, List<SpecializationThrowsData> exceptions) {
+    public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind, int order, List<SpecializationThrowsData> exceptions) {
         super(template);
+        this.node = node;
         this.order = order;
-        this.generic = false;
-        this.uninitialized = false;
-        this.polymorphic = false;
+        this.kind = kind;
         this.exceptions = exceptions;
 
         for (SpecializationThrowsData exception : exceptions) {
@@ -58,13 +59,8 @@
         }
     }
 
-    public SpecializationData(TemplateMethod template, boolean generic, boolean uninitialized, boolean polymorphic) {
-        super(template);
-        this.order = Specialization.DEFAULT_ORDER;
-        this.generic = generic;
-        this.uninitialized = uninitialized;
-        this.polymorphic = polymorphic;
-        this.exceptions = Collections.emptyList();
+    public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind) {
+        this(node, template, kind, Specialization.DEFAULT_ORDER, new ArrayList<SpecializationThrowsData>());
     }
 
     public void setReachable(boolean reachable) {
@@ -76,7 +72,7 @@
     }
 
     public boolean isPolymorphic() {
-        return polymorphic;
+        return kind == SpecializationKind.POLYMORPHIC;
     }
 
     @Override
@@ -99,20 +95,12 @@
             return false;
         }
 
-        for (ActualParameter parameter : getParameters()) {
-            if (!parameter.getSpecification().isSignature()) {
-                continue;
-            }
-            NodeChildData child = getNode().findChild(parameter.getSpecification().getName());
-            if (child == null) {
-                continue;
-            }
+        for (ActualParameter parameter : getSignatureParameters()) {
             ActualParameter genericParameter = getNode().getGenericSpecialization().findParameter(parameter.getLocalName());
             if (!parameter.getTypeSystemType().equals(genericParameter.getTypeSystemType())) {
                 return false;
             }
         }
-
         return true;
     }
 
@@ -126,12 +114,8 @@
         if (!getAssumptions().isEmpty()) {
             return true;
         }
-        for (ActualParameter parameter : getParameters()) {
-            NodeChildData child = getNode().findChild(parameter.getSpecification().getName());
-            if (child == null) {
-                continue;
-            }
-            ExecutableTypeData type = child.findExecutableType(context, parameter.getTypeSystemType());
+        for (ActualParameter parameter : getSignatureParameters()) {
+            ExecutableTypeData type = parameter.getSpecification().getExecution().getChild().findExecutableType(context, parameter.getTypeSystemType());
             if (type.hasUnexpectedValue(context)) {
                 return true;
             }
@@ -153,12 +137,12 @@
 
         SpecializationData m2 = (SpecializationData) other;
 
+        int kindOrder = kind.compareTo(m2.kind);
+        if (kindOrder != 0) {
+            return kindOrder;
+        }
         if (getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
             return getOrder() - m2.getOrder();
-        } else if (isUninitialized() ^ m2.isUninitialized()) {
-            return isUninitialized() ? -1 : 1;
-        } else if (isGeneric() ^ m2.isGeneric()) {
-            return isGeneric() ? 1 : -1;
         }
 
         if (getTemplate() != m2.getTemplate()) {
@@ -172,10 +156,6 @@
         return node;
     }
 
-    public void setNode(NodeData node) {
-        this.node = node;
-    }
-
     public void setGuards(List<GuardData> guards) {
         this.guards = guards;
     }
@@ -189,15 +169,15 @@
     }
 
     public boolean isSpecialized() {
-        return !isGeneric() && !isUninitialized() && !isPolymorphic();
+        return kind == SpecializationKind.SPECIALIZED;
     }
 
     public boolean isGeneric() {
-        return generic;
+        return kind == SpecializationKind.GENERIC;
     }
 
     public boolean isUninitialized() {
-        return uninitialized;
+        return kind == SpecializationKind.UNINITIALIZED;
     }
 
     public List<SpecializationThrowsData> getExceptions() {
@@ -254,20 +234,20 @@
 
     @Override
     public String toString() {
-        return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getSignature());
+        return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature());
     }
 
     public void forceFrame(TypeMirror frameType) {
         if (getParameters().isEmpty() || !Utils.typeEquals(getParameters().get(0).getType(), frameType)) {
             ParameterSpec frameSpec = getSpecification().findParameterSpec("frame");
             if (frameSpec != null) {
-                getParameters().add(0, new ActualParameter(frameSpec, frameType, -1, -1, false));
+                getParameters().add(0, new ActualParameter(frameSpec, frameType, -1, -1));
             }
         }
     }
 
     public boolean equalsGuards(SpecializationData specialization) {
-        if (assumptions.equals(specialization.getAssumptions()) && guards.equals(specialization.getGuards()) && getSignature().equalsParameters(specialization.getSignature())) {
+        if (assumptions.equals(specialization.getAssumptions()) && guards.equals(specialization.getGuards()) && getTypeSignature().equalsParameters(specialization.getTypeSignature())) {
             return true;
         }
         return false;
@@ -281,4 +261,5 @@
         }
         return false;
     }
+
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java	Tue Jan 07 22:36:23 2014 +0100
@@ -28,7 +28,7 @@
 
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature;
+import com.oracle.truffle.dsl.processor.template.TemplateMethod.TypeSignature;
 import com.oracle.truffle.dsl.processor.typesystem.*;
 
 /**
@@ -55,7 +55,7 @@
         this.specialization = data;
 
         this.assumptions.addAll(data.getAssumptions());
-        Signature sig = data.getSignature();
+        TypeSignature sig = data.getTypeSignature();
         for (int i = 1; i < sig.size(); i++) {
             typeGuards.add(new TypeGuard(sig.get(i), i - 1));
         }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.java	Tue Jan 07 21:52:07 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +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.node;
-
-import java.lang.annotation.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class SpecializationListenerParser extends NodeMethodParser<SpecializationListenerData> {
-
-    public SpecializationListenerParser(ProcessorContext context, NodeData node) {
-        super(context, node);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        return createDefaultMethodSpec(method, mirror, true, null);
-    }
-
-    @Override
-    protected ParameterSpec createReturnParameterSpec() {
-        return new ParameterSpec("void", getContext().getType(void.class));
-    }
-
-    @Override
-    public SpecializationListenerData create(TemplateMethod method, boolean invalid) {
-        return new SpecializationListenerData(method);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return SpecializationListener.class;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java	Tue Jan 07 22:36:23 2014 +0100
@@ -30,6 +30,7 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.node.SpecializationData.SpecializationKind;
 import com.oracle.truffle.dsl.processor.template.*;
 
 public class SpecializationMethodParser extends NodeMethodParser<SpecializationData> {
@@ -77,7 +78,7 @@
                 return Utils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass());
             }
         });
-        SpecializationData specialization = new SpecializationData(method, order, exceptionData);
+        SpecializationData specialization = new SpecializationData(getNode(), method, SpecializationKind.SPECIALIZED, order, exceptionData);
         List<String> guardDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards");
         specialization.setGuardDefinitions(guardDefs);
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java	Tue Jan 07 22:36:23 2014 +0100
@@ -33,56 +33,49 @@
     private TypeData typeSystemType;
     private TemplateMethod method;
     private final String localName;
-    private final int specificationIndex;
-    private final int varArgsIndex;
-    private final boolean implicit;
-    private final TypeMirror type;
+    private final int specificationVarArgsIndex;
+    private final int typeVarArgsIndex;
+    private final TypeMirror actualType;
 
-    public ActualParameter(ParameterSpec specification, TypeMirror actualType, int specificationIndex, int varArgsIndex, boolean implicit) {
+    public ActualParameter(ParameterSpec specification, TypeMirror actualType, int specificationVarArgsIndex, int typeVarArgsIndex) {
         this.specification = specification;
-        this.type = actualType;
+        this.actualType = actualType;
         this.typeSystemType = null;
 
-        this.specificationIndex = specificationIndex;
-        this.implicit = implicit;
-        String valueName = specification.getName() + "Value";
+        this.specificationVarArgsIndex = specificationVarArgsIndex;
 
-        if (specification.isIndexed()) {
-            valueName += specificationIndex;
+        String valueName = specification.getName() + "Value";
+        if (specificationVarArgsIndex > -1) {
+            valueName += specificationVarArgsIndex;
         }
-        this.varArgsIndex = varArgsIndex;
+        this.typeVarArgsIndex = typeVarArgsIndex;
         this.localName = valueName;
     }
 
-    public ActualParameter(ParameterSpec specification, TypeData actualType, int specificationIndex, int varArgsIndex, boolean implicit) {
-        this(specification, actualType.getPrimitiveType(), specificationIndex, varArgsIndex, implicit);
+    public ActualParameter(ParameterSpec specification, TypeData actualType, int specificationIndex, int varArgsIndex) {
+        this(specification, actualType.getPrimitiveType(), specificationIndex, varArgsIndex);
         this.typeSystemType = actualType;
     }
 
     public ActualParameter(ActualParameter parameter, TypeData otherType) {
-        this(parameter.specification, otherType, parameter.specificationIndex, parameter.varArgsIndex, parameter.implicit);
+        this(parameter.specification, otherType, parameter.specificationVarArgsIndex, parameter.typeVarArgsIndex);
     }
 
     public ActualParameter(ActualParameter parameter) {
         this.specification = parameter.specification;
-        this.type = parameter.type;
+        this.actualType = parameter.actualType;
         this.typeSystemType = parameter.typeSystemType;
-        this.specificationIndex = parameter.specificationIndex;
-        this.implicit = parameter.implicit;
+        this.specificationVarArgsIndex = parameter.specificationVarArgsIndex;
         this.localName = parameter.localName;
-        this.varArgsIndex = parameter.varArgsIndex;
+        this.typeVarArgsIndex = parameter.typeVarArgsIndex;
     }
 
-    public int getVarArgsIndex() {
-        return varArgsIndex;
+    public int getTypeVarArgsIndex() {
+        return typeVarArgsIndex;
     }
 
-    public boolean isImplicit() {
-        return implicit;
-    }
-
-    public int getSpecificationIndex() {
-        return specificationIndex;
+    public int getSpecificationVarArgsIndex() {
+        return specificationVarArgsIndex;
     }
 
     public String getLocalName() {
@@ -102,15 +95,15 @@
     }
 
     public TypeMirror getType() {
-        return type;
+        return actualType;
     }
 
     public TypeData getTypeSystemType() {
         return typeSystemType;
     }
 
-    public boolean isVarArgs() {
-        return varArgsIndex >= 0;
+    public boolean isTypeVarArgs() {
+        return typeVarArgsIndex >= 0;
     }
 
     public ActualParameter getPreviousParameter() {
@@ -119,6 +112,6 @@
 
     @Override
     public String toString() {
-        return Utils.getSimpleName(type);
+        return Utils.getSimpleName(actualType);
     }
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java	Tue Jan 07 22:36:23 2014 +0100
@@ -64,8 +64,8 @@
         }
         verifyExpectedMessages(context, log, childMessages);
 
-        for (Message message : getMessages()) {
-            emitDefault(context, baseElement, log, message);
+        for (int i = getMessages().size() - 1; i >= 0; i--) {
+            emitDefault(context, baseElement, log, getMessages().get(i));
         }
 
         for (MessageContainer sink : findChildContainers()) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java	Tue Jan 07 22:36:23 2014 +0100
@@ -27,42 +27,37 @@
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
 
 public class MethodSpec {
 
-    private final List<TypeMirror> implicitRequiredTypes = new ArrayList<>();
-
     private final ParameterSpec returnType;
     private final List<ParameterSpec> optional = new ArrayList<>();
     private final List<ParameterSpec> required = new ArrayList<>();
 
-    private int minimumRequiredArguments;
-    private boolean variableRequiredArguments;
+    private boolean ignoreAdditionalParameters;
+    private boolean ignoreAdditionalSpecifications;
+    private boolean variableRequiredParameters;
+
     private List<TypeDef> typeDefinitions;
 
     public MethodSpec(ParameterSpec returnType) {
         this.returnType = returnType;
     }
 
-    public void setMinimumRequiredArguments(int minimumRequiredArguments) {
-        this.minimumRequiredArguments = minimumRequiredArguments;
-    }
-
-    public int getMinimumRequiredArguments() {
-        return minimumRequiredArguments;
+    public void setVariableRequiredParameters(boolean variableRequiredParameters) {
+        this.variableRequiredParameters = variableRequiredParameters;
     }
 
-    public void setVariableRequiredArguments(boolean variableArguments) {
-        this.variableRequiredArguments = variableArguments;
+    public boolean isVariableRequiredParameters() {
+        return variableRequiredParameters;
     }
 
-    public boolean isVariableRequiredArguments() {
-        return variableRequiredArguments;
+    public void setIgnoreAdditionalParameters(boolean ignoreAdditionalParameter) {
+        this.ignoreAdditionalParameters = ignoreAdditionalParameter;
     }
 
-    public void addImplicitRequiredType(TypeMirror type) {
-        this.implicitRequiredTypes.add(type);
+    public boolean isIgnoreAdditionalParameters() {
+        return ignoreAdditionalParameters;
     }
 
     public void addOptional(ParameterSpec spec) {
@@ -74,10 +69,6 @@
         return spec;
     }
 
-    public List<TypeMirror> getImplicitRequiredTypes() {
-        return implicitRequiredTypes;
-    }
-
     public ParameterSpec getReturnType() {
         return returnType;
     }
@@ -158,15 +149,18 @@
             sep = ", ";
         }
 
-        for (ParameterSpec requiredSpec : getRequired()) {
+        for (int i = 0; i < getRequired().size(); i++) {
+            ParameterSpec requiredSpec = getRequired().get(i);
             b.append(sep);
-            if (requiredSpec.getCardinality() == Cardinality.MANY) {
-                b.append("{");
+
+            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
+                b.append(("{"));
             }
             b.append(createTypeSignature(requiredSpec, false));
-            if (requiredSpec.getCardinality() == Cardinality.MANY) {
-                b.append("}");
+            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
+                b.append(("}"));
             }
+
             sep = ", ";
         }
 
@@ -234,4 +228,12 @@
         }
     }
 
+    public void setIgnoreAdditionalSpecifications(boolean ignoreAdditoinalSpecifications) {
+        this.ignoreAdditionalSpecifications = ignoreAdditoinalSpecifications;
+    }
+
+    public boolean isIgnoreAdditionalSpecifications() {
+        return ignoreAdditionalSpecifications;
+    }
+
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java	Tue Jan 07 22:36:23 2014 +0100
@@ -27,44 +27,53 @@
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
-import com.oracle.truffle.dsl.processor.template.MethodSpec.*;
+import com.oracle.truffle.dsl.processor.node.*;
+import com.oracle.truffle.dsl.processor.template.MethodSpec.TypeDef;
 
 public class ParameterSpec {
 
     private final String name;
     private final List<TypeMirror> allowedTypes;
 
-    /** Cardinality one or multiple. */
-    private Cardinality cardinality = Cardinality.ONE;
-    /** Type is part of the method signature. Relevant for comparisons. */
-    private boolean signature;
-    /** Type must be indexed when parsing. */
-    private boolean indexed;
     /** Type is bound to local final variable. */
     private boolean local;
-
-    private TypeDef typeDefinition;
+    private boolean signature;
 
-    public ParameterSpec(String name, TypeMirror... allowedTypes) {
-        this(name, Arrays.asList(allowedTypes));
-    }
+    /** Optional bound execution of node. */
+    private NodeExecutionData execution;
+    private TypeDef typeDefinition;
 
     public ParameterSpec(String name, List<TypeMirror> allowedTypes) {
         this.name = name;
         this.allowedTypes = allowedTypes;
     }
 
+    public ParameterSpec(String name, TypeMirror type) {
+        this(name, Arrays.asList(type));
+    }
+
     public ParameterSpec(ParameterSpec o, List<TypeMirror> allowedTypes) {
         this.name = o.name;
-        this.cardinality = o.cardinality;
-        this.signature = o.signature;
-        this.indexed = o.indexed;
         this.local = o.local;
         this.typeDefinition = o.typeDefinition;
+        this.execution = o.execution;
+        this.signature = o.signature;
         this.allowedTypes = allowedTypes;
     }
 
+    public NodeExecutionData getExecution() {
+        return execution;
+    }
+
+    public void setExecution(NodeExecutionData executionData) {
+        this.execution = executionData;
+        this.signature = execution != null;
+    }
+
+    public void setSignature(boolean signature) {
+        this.signature = signature;
+    }
+
     void setTypeDefinition(TypeDef typeDefinition) {
         this.typeDefinition = typeDefinition;
     }
@@ -73,10 +82,6 @@
         return typeDefinition;
     }
 
-    public void setSignature(boolean signature) {
-        this.signature = signature;
-    }
-
     public void setLocal(boolean local) {
         this.local = local;
     }
@@ -89,26 +94,10 @@
         return local;
     }
 
-    public boolean isIndexed() {
-        return indexed;
-    }
-
-    public void setIndexed(boolean indexed) {
-        this.indexed = indexed;
-    }
-
-    public void setCardinality(Cardinality cardinality) {
-        this.cardinality = cardinality;
-    }
-
     public String getName() {
         return name;
     }
 
-    public Cardinality getCardinality() {
-        return cardinality;
-    }
-
     public List<TypeMirror> getAllowedTypes() {
         return allowedTypes;
     }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java	Tue Jan 07 22:36:23 2014 +0100
@@ -29,6 +29,7 @@
 
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.typesystem.*;
+import com.oracle.truffle.dsl.processor.util.*;
 
 /**
  * Note: this class has a natural ordering that is inconsistent with equals.
@@ -133,6 +134,14 @@
         return requiredParameters;
     }
 
+    public Iterable<ActualParameter> getSignatureParameters() {
+        return new FilteredIterable<>(getParameters(), new Predicate<ActualParameter>() {
+            public boolean evaluate(ActualParameter value) {
+                return value.getSpecification().isSignature();
+            }
+        });
+    }
+
     public List<ActualParameter> getParameters() {
         return parameters;
     }
@@ -202,23 +211,19 @@
         return prev;
     }
 
+    @SuppressWarnings("unused")
     public int getSignatureSize() {
         int signatureSize = 0;
-        for (ActualParameter parameter : getParameters()) {
-            if (!parameter.getSpecification().isSignature()) {
-                continue;
-            }
+        for (ActualParameter parameter : getSignatureParameters()) {
             signatureSize++;
         }
         return signatureSize;
     }
 
-    public Signature getSignature() {
-        Signature signature = new Signature();
-        for (ActualParameter parameter : getReturnTypeAndParameters()) {
-            if (!parameter.getSpecification().isSignature()) {
-                continue;
-            }
+    public TypeSignature getTypeSignature() {
+        TypeSignature signature = new TypeSignature();
+        signature.types.add(getReturnType().getTypeSystemType());
+        for (ActualParameter parameter : getSignatureParameters()) {
             TypeData typeData = parameter.getTypeSystemType();
             if (typeData != null) {
                 signature.types.add(typeData);
@@ -241,7 +246,7 @@
         return null;
     }
 
-    public void updateSignature(Signature signature) {
+    public void updateSignature(TypeSignature signature) {
         // TODO(CH): fails in normal usage - output ok though
         // assert signature.size() >= 1;
 
@@ -299,8 +304,8 @@
             throw new IllegalStateException("Cannot compare two methods with different type systems.");
         }
 
-        List<TypeMirror> signature1 = getSignatureTypes(getReturnTypeAndParameters());
-        List<TypeMirror> signature2 = getSignatureTypes(compareMethod.getReturnTypeAndParameters());
+        List<TypeMirror> signature1 = getSignatureTypes(this);
+        List<TypeMirror> signature2 = getSignatureTypes(compareMethod);
         if (signature1.size() != signature2.size()) {
             return signature2.size() - signature1.size();
         }
@@ -349,25 +354,24 @@
         return Utils.getSimpleName(signature1).compareTo(Utils.getSimpleName(signature2));
     }
 
-    public static List<TypeMirror> getSignatureTypes(List<ActualParameter> params) {
+    public static List<TypeMirror> getSignatureTypes(TemplateMethod method) {
         List<TypeMirror> types = new ArrayList<>();
-        for (ActualParameter param : params) {
-            if (param.getSpecification().isSignature()) {
-                types.add(param.getType());
-            }
+        types.add(method.getReturnType().getType());
+        for (ActualParameter param : method.getSignatureParameters()) {
+            types.add(param.getType());
         }
         return types;
     }
 
-    public static class Signature implements Iterable<TypeData>, Comparable<Signature> {
+    public static class TypeSignature implements Iterable<TypeData>, Comparable<TypeSignature> {
 
         final List<TypeData> types;
 
-        public Signature() {
+        public TypeSignature() {
             this.types = new ArrayList<>();
         }
 
-        public Signature(List<TypeData> signature) {
+        public TypeSignature(List<TypeData> signature) {
             this.types = signature;
         }
 
@@ -384,7 +388,7 @@
             return types.get(index);
         }
 
-        public int compareTo(Signature other) {
+        public int compareTo(TypeSignature other) {
             if (this == other) {
                 return 0;
             } else if (types.size() != other.types.size()) {
@@ -406,7 +410,7 @@
             return 0;
         }
 
-        public Signature combine(Signature genericSignature, Signature other) {
+        public TypeSignature combine(TypeSignature genericSignature, TypeSignature other) {
             assert types.size() == other.types.size();
             assert genericSignature.types.size() == other.types.size();
 
@@ -414,7 +418,7 @@
                 return this;
             }
 
-            Signature signature = new Signature();
+            TypeSignature signature = new TypeSignature();
             for (int i = 0; i < types.size(); i++) {
                 TypeData type1 = types.get(i);
                 TypeData type2 = other.types.get(i);
@@ -427,7 +431,7 @@
             return signature;
         }
 
-        public boolean equalsParameters(Signature other) {
+        public boolean equalsParameters(TypeSignature other) {
             if (size() != other.size()) {
                 return false;
             }
@@ -436,8 +440,8 @@
 
         @Override
         public boolean equals(Object obj) {
-            if (obj instanceof Signature) {
-                return ((Signature) obj).types.equals(types);
+            if (obj instanceof TypeSignature) {
+                return ((TypeSignature) obj).types.equals(types);
             }
             return super.equals(obj);
         }
@@ -451,7 +455,7 @@
             return types.toString();
         }
 
-        public boolean hasAnyParameterMatch(Signature other) {
+        public boolean hasAnyParameterMatch(TypeSignature other) {
             for (int i = 1; i < types.size(); i++) {
                 TypeData type1 = types.get(i);
                 TypeData type2 = other.types.get(i);
@@ -462,7 +466,7 @@
             return false;
         }
 
-        public boolean isCompatibleTo(Signature signature) {
+        public boolean isCompatibleTo(TypeSignature signature) {
             if (size() != signature.size()) {
                 return false;
             }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java	Tue Jan 07 22:36:23 2014 +0100
@@ -31,9 +31,7 @@
 import javax.lang.model.type.*;
 import javax.lang.model.util.*;
 
-import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
 import com.oracle.truffle.dsl.processor.typesystem.*;
 
 public abstract class TemplateMethodParser<T extends Template, E extends TemplateMethod> {
@@ -142,19 +140,23 @@
         methodSpecification.applyTypeDefinitions("types");
 
         String id = method.getSimpleName().toString();
-        AnnotationMirror idAnnotation = Utils.findAnnotationMirror(context.getEnvironment(), method, NodeId.class);
-        if (idAnnotation != null) {
-            id = Utils.getAnnotationValue(String.class, idAnnotation, "value");
+        TypeMirror returnType = method.getReturnType();
+        List<TypeMirror> parameterTypes = new ArrayList<>();
+        for (VariableElement var : method.getParameters()) {
+            parameterTypes.add(var.asType());
         }
 
-        ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
+        return parseImpl(methodSpecification, id, method, annotation, returnType, parameterTypes);
+    }
 
-        ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, -1, false);
+    private E parseImpl(MethodSpec methodSpecification, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType, List<TypeMirror> parameterTypes) {
+        ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
+        ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, template, -1, -1);
         if (returnTypeMirror == null) {
             if (emitErrors) {
                 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true);
                 String expectedReturnType = returnTypeSpec.toSignatureString(true);
-                String actualReturnType = Utils.getSimpleName(method.getReturnType());
+                String actualReturnType = Utils.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()));
@@ -165,16 +167,11 @@
             }
         }
 
-        List<TypeMirror> parameterTypes = new ArrayList<>();
-        for (VariableElement var : method.getParameters()) {
-            parameterTypes.add(var.asType());
-        }
-
-        List<ActualParameter> parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method.isVarArgs());
+        List<ActualParameter> parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method != null ? method.isVarArgs() : false);
         if (parameters == null) {
-            if (isEmitErrors()) {
+            if (isEmitErrors() && method != null) {
                 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true);
-                String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method),
+                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;
@@ -186,18 +183,15 @@
         return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters), false);
     }
 
-    private static String createActualSignature(MethodSpec spec, ExecutableElement method) {
+    private static String createActualSignature(ExecutableElement method) {
         StringBuilder b = new StringBuilder("(");
         String sep = "";
-        for (TypeMirror implicitType : spec.getImplicitRequiredTypes()) {
-            b.append(sep);
-            b.append("implicit " + Utils.getSimpleName(implicitType));
-            sep = ", ";
-        }
-        for (VariableElement var : method.getParameters()) {
-            b.append(sep);
-            b.append(Utils.getSimpleName(var.asType()));
-            sep = ", ";
+        if (method != null) {
+            for (VariableElement var : method.getParameters()) {
+                b.append(sep);
+                b.append(Utils.getSimpleName(var.asType()));
+                sep = ", ";
+            }
         }
         b.append(")");
         return b.toString();
@@ -207,34 +201,29 @@
      * 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. All those remaining parameters must
-     * be consumed otherwise its an error.
+     * ones are cut and used to parse the optional parameters.
      */
     private List<ActualParameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes, boolean varArgs) {
-        List<TypeMirror> implicitTypes = spec.getImplicitRequiredTypes();
-
-        int offset = -1;
         List<ActualParameter> parsedRequired = null;
-        ConsumableListIterator<TypeMirror> types = null;
-        while (parsedRequired == null && offset < parameterTypes.size()) {
-            offset++;
-            types = new ConsumableListIterator<>(new ArrayList<>(implicitTypes));
-            types.data.addAll(parameterTypes.subList(offset, parameterTypes.size()));
-            parsedRequired = parseParametersRequired(spec, types, varArgs);
+        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 && offset >= 0) {
+        if (parsedRequired == null) {
             return null;
         }
 
-        List<TypeMirror> potentialOptionals;
-        if (offset == -1) {
-            potentialOptionals = parameterTypes;
-        } else {
-            potentialOptionals = parameterTypes.subList(0, offset);
+        if (parsedRequired.isEmpty() && offset == 0) {
+            offset = parameterTypes.size();
         }
-        types = new ConsumableListIterator<>(potentialOptionals);
-        List<ActualParameter> parsedOptionals = parseParametersOptional(spec, types);
+        List<TypeMirror> potentialOptionals = parameterTypes.subList(0, offset);
+        List<ActualParameter> parsedOptionals = parseParametersOptional(spec, potentialOptionals);
         if (parsedOptionals == null) {
             return null;
         }
@@ -245,99 +234,104 @@
         return finalParameters;
     }
 
-    private List<ActualParameter> parseParametersOptional(MethodSpec spec, ConsumableListIterator<TypeMirror> types) {
+    private List<ActualParameter> parseParametersOptional(MethodSpec spec, List<TypeMirror> types) {
         List<ActualParameter> parsedParams = new ArrayList<>();
-        // parse optional parameters
-        ConsumableListIterator<ParameterSpec> optionals = new ConsumableListIterator<>(spec.getOptional());
-        for (TypeMirror type : types) {
-            int oldIndex = types.getIndex();
-            int optionalCount = 1;
-            for (ParameterSpec paramspec : optionals) {
-                ActualParameter optionalParam = matchParameter(paramspec, type, template, 0, -1, false);
+
+        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);
+                ActualParameter optionalParam = matchParameter(specification, actualType, template, -1, -1);
                 if (optionalParam != null) {
-                    optionals.consume(optionalCount);
-                    types.consume();
                     parsedParams.add(optionalParam);
-                    break;
+                    typeStartIndex = typeIndex + 1;
+                    continue outer;
                 }
-                optionalCount++;
-            }
-            if (oldIndex == types.getIndex()) {
-                // nothing found anymore skip optional
-                break;
             }
         }
-        if (types.getIndex() <= types.data.size() - 1) {
+
+        if (typeStartIndex < types.size()) {
+            // not enough types found
             return null;
         }
         return parsedParams;
     }
 
-    private List<ActualParameter> parseParametersRequired(MethodSpec spec, ConsumableListIterator<TypeMirror> types, boolean varArgs) {
+    private List<ActualParameter> parseParametersRequired(MethodSpec spec, List<TypeMirror> types, boolean typeVarArgs) {
         List<ActualParameter> parsedParams = new ArrayList<>();
+        List<ParameterSpec> specifications = spec.getRequired();
+        boolean specVarArgs = spec.isVariableRequiredParameters();
+        int typeIndex = 0;
+        int specificationIndex = 0;
 
-        int varArgsParameterIndex = -1;
-        int specificationParameterIndex = 0;
-        ConsumableListIterator<ParameterSpec> required = new ConsumableListIterator<>(spec.getRequired());
-        while (required.get() != null || types.get() != null) {
-            if (required.get() == null || types.get() == null) {
-                if (required.get() != null && required.get().getCardinality() == Cardinality.MANY) {
-                    required.consume();
-                    specificationParameterIndex = 0;
-                    continue;
+        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;
             }
-            TypeMirror actualType = types.get();
-            if (varArgs && types.isLast()) {
-                if (actualType.getKind() == TypeKind.ARRAY) {
-                    actualType = ((ArrayType) actualType).getComponentType();
-                }
-                varArgsParameterIndex++;
+
+            ActualParameter resolvedParameter = matchParameter(specification, actualType, template, specVarArgsIndex, typeVarArgsIndex);
+            if (resolvedParameter == null) {
+                return null;
             }
-            boolean implicit = types.getIndex() < spec.getImplicitRequiredTypes().size();
-            ActualParameter resolvedParameter = matchParameter(required.get(), actualType, template, specificationParameterIndex, varArgsParameterIndex, implicit);
-            if (resolvedParameter == null) {
-                if (required.get().getCardinality() == Cardinality.MANY) {
-                    required.consume();
-                    continue;
-                }
-                // direct mismatch but required -> error
-                return null;
+            parsedParams.add(resolvedParameter);
+            typeIndex++;
+            specificationIndex++;
+        }
+
+        if (typeIndex < types.size()) {
+            // additional types available
+            if (spec.isIgnoreAdditionalParameters()) {
+                return parsedParams;
             } else {
-                parsedParams.add(resolvedParameter);
-
-                if (varArgs && types.isLast()) {
-                    /* Both varargs spec and varargs definition. Need to consume to terminate. */
-                    if (required.get().getCardinality() == Cardinality.MANY) {
-                        types.consume();
-                    }
-                } else {
-                    types.consume();
-                }
-
-                if (required.get().getCardinality() == Cardinality.ONE) {
-                    required.consume();
-                    specificationParameterIndex = 0;
-                } else if (required.get().getCardinality() == Cardinality.MANY) {
-                    specificationParameterIndex++;
-                }
+                return null;
             }
         }
 
-        if (!types.toList().isEmpty() && !(varArgs && types.isLast())) {
-            // additional types -> error
-            return null;
-        }
-
-        if (!required.toList().isEmpty() && !spec.isVariableRequiredArguments()) {
-            // additional specifications -> error
-            return null;
-        }
         return parsedParams;
     }
 
-    private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int specificationIndex, int varArgsIndex, boolean implicit) {
+    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;
+        }
+    }
+
+    protected final ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int specificationIndex, int varArgsIndex) {
         TypeMirror resolvedType = mirror;
         if (hasError(resolvedType)) {
             resolvedType = context.resolveNotYetCompiledType(mirror, originalTemplate);
@@ -349,63 +343,13 @@
 
         TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType);
         if (resolvedTypeData != null) {
-            return new ActualParameter(specification, resolvedTypeData, specificationIndex, varArgsIndex, implicit);
+            return new ActualParameter(specification, resolvedTypeData, specificationIndex, varArgsIndex);
         } else {
-            return new ActualParameter(specification, resolvedType, specificationIndex, varArgsIndex, implicit);
+            return new ActualParameter(specification, resolvedType, specificationIndex, varArgsIndex);
         }
     }
 
-    /* Helper class for parsing. */
-    private static class ConsumableListIterator<E> implements Iterable<E> {
-
-        private final List<E> data;
-        private int index;
-
-        public ConsumableListIterator(List<E> data) {
-            this.data = data;
-        }
-
-        public E get() {
-            if (index >= data.size()) {
-                return null;
-            }
-            return data.get(index);
-        }
-
-        public boolean isLast() {
-            return index == data.size() - 1;
-        }
-
-        public E consume() {
-            return consume(1);
-        }
-
-        public E consume(int count) {
-            if (index + count <= data.size()) {
-                index += count;
-                return get();
-            } else {
-                throw new ArrayIndexOutOfBoundsException(count + 1);
-            }
-        }
-
-        public int getIndex() {
-            return index;
-        }
-
-        @Override
-        public Iterator<E> iterator() {
-            return toList().iterator();
-        }
-
-        public List<E> toList() {
-            if (index < data.size()) {
-                return data.subList(index, data.size());
-            } else {
-                return Collections.<E> emptyList();
-            }
-        }
-
+    public final E create(String id, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List<TypeMirror> parameterTypes) {
+        return parseImpl(createSpecification(methodMetadata, mirror), id, methodMetadata, mirror, returnType, parameterTypes);
     }
-
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateParser.java	Tue Jan 07 21:52:07 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +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.template;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.*;
-
-public abstract class TemplateParser<M extends Template> extends AbstractParser<M> {
-
-    public TemplateParser(ProcessorContext c) {
-        super(c);
-    }
-
-    protected void verifyExclusiveMethodAnnotation(Template template, Class<?>... annotationTypes) {
-        List<ExecutableElement> methods = ElementFilter.methodsIn(template.getTemplateType().getEnclosedElements());
-        for (ExecutableElement method : methods) {
-            List<AnnotationMirror> foundAnnotations = new ArrayList<>();
-            for (int i = 0; i < annotationTypes.length; i++) {
-                Class<?> annotationType = annotationTypes[i];
-                AnnotationMirror mirror = Utils.findAnnotationMirror(context.getEnvironment(), method, annotationType);
-                if (mirror != null) {
-                    foundAnnotations.add(mirror);
-                }
-            }
-            if (foundAnnotations.size() > 1) {
-                List<String> annotationNames = new ArrayList<>();
-                for (AnnotationMirror mirror : foundAnnotations) {
-                    annotationNames.add("@" + Utils.getSimpleName(mirror.getAnnotationType()));
-                }
-
-                template.addError("Non exclusive usage of annotations %s.", annotationNames);
-            }
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java	Tue Jan 07 22:36:23 2014 +0100
@@ -23,10 +23,8 @@
 package com.oracle.truffle.dsl.processor.typesystem;
 
 import java.lang.annotation.*;
-import java.util.*;
 
 import javax.lang.model.element.*;
-import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.node.*;
@@ -53,16 +51,18 @@
     }
 
     @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.setVariableRequiredArguments(true);
+        spec.setIgnoreAdditionalSpecifications(true);
         spec.getRequired().clear();
 
         for (ActualParameter parameter : specialization.getRequiredParameters()) {
-            List<TypeMirror> assignableTypes = Utils.getAssignableTypes(getContext(), parameter.getType());
-            ParameterSpec paramSpec = new ParameterSpec(parameter.getLocalName(), assignableTypes);
-            paramSpec.setSignature(true);
-            spec.addRequired(paramSpec);
+            spec.addRequired(new ParameterSpec(parameter.getSpecification(), Utils.getAssignableTypes(getContext(), parameter.getType())));
         }
 
         return spec;
@@ -80,31 +80,7 @@
 
     @Override
     public GuardData create(TemplateMethod method, boolean invalid) {
-        GuardData guard = new GuardData(method, specialization, negated);
-        /*
-         * Update parameters in way that parameter specifications match again the node field names
-         * etc.
-         */
-        List<ActualParameter> newParameters = new ArrayList<>();
-        for (ActualParameter parameter : guard.getParameters()) {
-            ActualParameter specializationParameter = specialization.findParameter(parameter.getSpecification().getName());
-            if (specializationParameter == null) {
-                newParameters.add(parameter);
-            } else {
-                ActualParameter p;
-                if (parameter.getTypeSystemType() != null) {
-                    p = new ActualParameter(specializationParameter.getSpecification(), parameter.getTypeSystemType(), specializationParameter.getSpecificationIndex(),
-                                    specializationParameter.getVarArgsIndex(), parameter.isImplicit());
-                } else {
-                    p = new ActualParameter(specializationParameter.getSpecification(), parameter.getType(), specializationParameter.getSpecificationIndex(),
-                                    specializationParameter.getVarArgsIndex(), parameter.isImplicit());
-                }
-                newParameters.add(p);
-            }
-        }
-        guard.setParameters(newParameters);
-
-        return guard;
+        return new GuardData(method, specialization, negated);
     }
 
     @Override
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java	Tue Jan 07 22:36:23 2014 +0100
@@ -50,7 +50,7 @@
             types.add(typeData.getPrimitiveType());
         }
         MethodSpec spec = new MethodSpec(new ParameterSpec("target", types));
-        spec.addRequired(new ParameterSpec("source", types)).setSignature(true);
+        spec.addRequired(new ParameterSpec("source", types));
         return spec;
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java	Tue Jan 07 22:36:23 2014 +0100
@@ -35,7 +35,7 @@
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.template.*;
 
-public class TypeSystemParser extends TemplateParser<TypeSystemData> {
+public class TypeSystemParser extends AbstractParser<TypeSystemData> {
 
     public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(TypeSystem.class, ExpectError.class);
 
@@ -115,6 +115,28 @@
         return typeSystem;
     }
 
+    protected void verifyExclusiveMethodAnnotation(Template template, Class<?>... annotationTypes) {
+        List<ExecutableElement> methods = ElementFilter.methodsIn(template.getTemplateType().getEnclosedElements());
+        for (ExecutableElement method : methods) {
+            List<AnnotationMirror> foundAnnotations = new ArrayList<>();
+            for (int i = 0; i < annotationTypes.length; i++) {
+                Class<?> annotationType = annotationTypes[i];
+                AnnotationMirror mirror = Utils.findAnnotationMirror(context.getEnvironment(), method, annotationType);
+                if (mirror != null) {
+                    foundAnnotations.add(mirror);
+                }
+            }
+            if (foundAnnotations.size() > 1) {
+                List<String> annotationNames = new ArrayList<>();
+                for (AnnotationMirror mirror : foundAnnotations) {
+                    annotationNames.add("@" + Utils.getSimpleName(mirror.getAnnotationType()));
+                }
+
+                template.addError("Non exclusive usage of annotations %s.", annotationNames);
+            }
+        }
+    }
+
     private static void verifyGenericTypeChecksAndCasts(TypeSystemData typeSystem) {
         for (TypeData type : typeSystem.getTypes()) {
             if (!type.getTypeChecks().isEmpty()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Filterator.java	Tue Jan 07 22:36:23 2014 +0100
@@ -0,0 +1,86 @@
+/*
+ * 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.util;
+
+import java.util.*;
+
+public class Filterator<T> implements Iterator<T> {
+
+    private final Predicate<T> includePredicate;
+    private final Iterator<T> elements;
+
+    private boolean hasCached;
+    private T cached;
+
+    public Filterator(Iterator<T> elements, Predicate<T> includePredicate) {
+        this.elements = elements;
+        this.includePredicate = includePredicate;
+    }
+
+    public boolean hasNext() {
+        if (hasCached) {
+            return true;
+        }
+        nextValue();
+        return hasCached;
+    }
+
+    private void nextValue() {
+        while (!hasCached && elements.hasNext()) {
+            T element = elements.next();
+            if (includePredicate.evaluate(element)) {
+                cached = element;
+                hasCached = true;
+            }
+        }
+    }
+
+    public T next() {
+        T foundCached = getCached();
+        if (foundCached != null) {
+            return foundCached;
+        } else {
+            nextValue();
+            if (!hasCached) {
+                throw new NoSuchElementException();
+            }
+            return getCached();
+        }
+    }
+
+    private T getCached() {
+        if (hasCached) {
+            hasCached = false;
+            T value = cached;
+            cached = null;
+            return value;
+        }
+        return null;
+    }
+
+    @Override
+    public void remove() {
+        elements.remove();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/FilteredIterable.java	Tue Jan 07 22:36:23 2014 +0100
@@ -0,0 +1,41 @@
+/*
+ * 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.util;
+
+import java.util.*;
+
+public class FilteredIterable<E> implements Iterable<E> {
+
+    private final Iterable<E> delegate;
+    private final Predicate<E> containedPredicate;
+
+    public FilteredIterable(Iterable<E> delegate, Predicate<E> containedPredicate) {
+        this.delegate = delegate;
+        this.containedPredicate = containedPredicate;
+    }
+
+    public Iterator<E> iterator() {
+        return new Filterator<>(delegate.iterator(), containedPredicate);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Predicate.java	Tue Jan 07 22:36:23 2014 +0100
@@ -0,0 +1,29 @@
+/*
+ * 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.util;
+
+public interface Predicate<T> {
+
+    boolean evaluate(T value);
+
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java	Tue Jan 07 21:52:07 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java	Tue Jan 07 22:36:23 2014 +0100
@@ -16,7 +16,7 @@
  * 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
+ * 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.
  */