changeset 13528:5a0c694ef735

Truffle-DSL: Removed API classes NodeId, NodeContainer and SpecializationListener.
author Christian Humer <christian.humer@gmail.com>
date Tue, 07 Jan 2014 18:52:32 +0100
parents 25ecb47a6d0e
children 856c2c294f84
files graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BoxedString.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeContainerTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/package-info.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeContainer.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeId.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/SpecializationListener.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java
diffstat 25 files changed, 830 insertions(+), 1463 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 18:52:32 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();
+    }
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java	Tue Jan 07 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java	Tue Jan 07 18:52:32 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 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java	Tue Jan 07 18:52:32 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 12:22:47 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 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java	Tue Jan 07 18:52:32 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;
         }
 
     }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java	Tue Jan 07 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java	Tue Jan 07 18:52:32 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 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Tue Jan 07 18:52:32 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 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/package-info.java	Tue Jan 07 18:52:32 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 12:22:47 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 12:22:47 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 12:22:47 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/GenericParser.java	Tue Jan 07 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java	Tue Jan 07 18:52:32 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> {
@@ -57,8 +58,7 @@
 
     @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 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java	Tue Jan 07 18:52:32 2014 +0100
@@ -45,24 +45,20 @@
         }
     }
 
-    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 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) {
-        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;
@@ -72,6 +68,10 @@
         this.cardinality = cardinality;
     }
 
+    void setParentNode(NodeData parentNode) {
+        this.parentNode = parentNode;
+    }
+
     public List<NodeChildData> getExecuteWith() {
         return executeWith;
     }
@@ -81,12 +81,12 @@
     }
 
     public boolean needsImplicitCast(ProcessorContext context) {
-        if (!parent.needsRewrites(context)) {
+        if (!parentNode.needsRewrites(context)) {
             return false;
         }
 
         boolean used = false;
-        for (NodeExecutionData execution : parent.getChildExecutions()) {
+        for (NodeExecutionData execution : parentNode.getChildExecutions()) {
             if (execution.getChild() == this) {
                 used = true;
                 break;
@@ -100,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);
         }
@@ -108,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() {
@@ -134,7 +134,7 @@
     }
 
     void setNode(NodeData nodeData) {
-        this.nodeData = nodeData;
+        this.childNode = nodeData;
         if (nodeData != null) {
             getMessages().addAll(nodeData.collectMessages());
         }
@@ -153,7 +153,7 @@
     }
 
     public NodeData getNodeData() {
-        return nodeData;
+        return childNode;
     }
 
     public String getName() {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Tue Jan 07 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Tue Jan 07 18:52:32 2014 +0100
@@ -47,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";
 
@@ -70,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) {
@@ -110,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"));
@@ -439,11 +408,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) {
@@ -525,15 +492,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);
                 }
 
@@ -572,7 +542,7 @@
             }
 
             List<NodeData> children = node.getNodeDeclaringChildren();
-            if (node.getParent() == null && children.size() > 0) {
+            if (node.getDeclaringNode() == null && children.size() > 0) {
                 clazz.add(createGetFactories(node));
             }
 
@@ -755,7 +725,7 @@
         }
 
         private String instanceVarName(NodeData node) {
-            if (node.getParent() != null) {
+            if (node.getDeclaringNode() != null) {
                 return Utils.firstLetterLowerCase(factoryClassName(node)) + "Instance";
             } else {
                 return "instance";
@@ -808,9 +778,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) {
@@ -950,7 +920,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()));
@@ -1144,8 +1114,7 @@
         }
 
         private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) {
-            String name = executeCachedName(polymorph);
-            CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), name);
+            CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_POLYMORPHIC_NAME);
             addInternalValueParameters(cachedExecute, polymorph, true, true);
 
             ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0);
@@ -1305,8 +1274,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()) {
@@ -1330,7 +1297,7 @@
 
             boolean firstUnreachable = true;
             for (SpecializationData current : node.getSpecializations()) {
-                if (current.isUninitialized() || current.isReachable()) {
+                if (current.isReachable()) {
                     continue;
                 }
                 if (firstUnreachable) {
@@ -1347,7 +1314,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);
@@ -1380,7 +1347,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();
@@ -1751,7 +1718,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();
         }
@@ -1829,7 +1796,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();
 
@@ -1840,7 +1807,7 @@
             builder.startStatement().startCall("currentCopy", "setNext0").startNew(uninitializedName).string(currentNode).end().end().end();
 
             builder.startReturn();
-            builder.startCall("currentCopy.next0", executeCachedName(node.getGenericPolymorphicSpecialization()));
+            builder.startCall("currentCopy.next0", EXECUTE_POLYMORPHIC_NAME);
             addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, true, null);
             builder.end();
             builder.end();
@@ -1848,14 +1815,6 @@
             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);
@@ -2302,8 +2261,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();
@@ -2311,11 +2269,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, true, null);
             execute.end();
 
-            TypeData sourceType = generic.getReturnType().getTypeSystemType();
+            TypeData sourceType = polymorphic.getReturnType().getTypeSystemType();
 
             builder.tree(createExpectExecutableType(node, sourceType, currentExecutable, execute.getRoot()));
 
@@ -2505,7 +2463,7 @@
             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));
 
@@ -2602,8 +2560,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));
 
@@ -2709,9 +2671,9 @@
 
             CodeTypeElement clazz = getElement();
 
-            final SpecializationData polymorphic = node.getGenericPolymorphicSpecialization();
-
-            ExecutableElement executeCached = nodeGen.getMethod(executeCachedName(polymorphic));
+            final SpecializationData polymorphic = node.getPolymorphicSpecialization();
+
+            ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_POLYMORPHIC_NAME);
             // ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached,
             // node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType());
 
@@ -2729,7 +2691,7 @@
                 builder.tree(createAppendPolymorphic(builder, specialization));
             } else {
                 CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder);
-                elseBuilder.startReturn().startCall("this.next0", executeCachedName(polymorphic));
+                elseBuilder.startReturn().startCall("this.next0", EXECUTE_POLYMORPHIC_NAME);
                 addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true, null);
                 elseBuilder.end().end();
 
@@ -2759,7 +2721,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();
 
@@ -2777,7 +2739,7 @@
 
             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();
@@ -2950,7 +2912,7 @@
 
             CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent);
             if (specialization.isPolymorphic()) {
-                returnBuilder.startCall("next0", executeCachedName(specialization));
+                returnBuilder.startCall("next0", EXECUTE_POLYMORPHIC_NAME);
                 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true, null);
                 returnBuilder.end();
             } else if (specialization.isUninitialized()) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java	Tue Jan 07 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java	Tue Jan 07 18:52:32 2014 +0100
@@ -34,58 +34,57 @@
 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<NodeExecutionData> childExecutions;
-    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 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;
+
+        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 void addEnclosedNode(NodeData node) {
+        this.enclosingNodes.add(node);
+        node.declaringNode = this;
     }
 
     public List<NodeExecutionData> getChildExecutions() {
         return childExecutions;
     }
 
-    void setChildExecutions(List<NodeExecutionData> signature) {
-        this.childExecutions = signature;
-    }
-
     public int getSignatureSize() {
         if (getSpecializations() != null && !getSpecializations().isEmpty()) {
             return getSpecializations().get(0).getSignatureSize();
@@ -122,7 +121,7 @@
         return polymorphicDepth > 1;
     }
 
-    void setPolymorphicDepth(int polymorphicDepth) {
+    public void setPolymorphicDepth(int polymorphicDepth) {
         this.polymorphicDepth = polymorphicDepth;
     }
 
@@ -130,43 +129,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);
@@ -178,9 +153,6 @@
                 }
             }
         }
-        if (specializationListeners != null) {
-            containerChildren.addAll(specializationListeners);
-        }
         if (executableTypes != null) {
             containerChildren.addAll(getExecutableTypes());
         }
@@ -212,16 +184,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;
     }
@@ -236,7 +201,7 @@
 
         boolean noSpecialization = true;
         for (SpecializationData specialization : specializations) {
-            noSpecialization = noSpecialization && specialization.isGeneric() || specialization.isUninitialized();
+            noSpecialization = noSpecialization && !specialization.isSpecialized();
         }
         return !noSpecialization;
     }
@@ -254,7 +219,7 @@
 
     public List<NodeData> getNodeDeclaringChildren() {
         List<NodeData> nodeChildren = new ArrayList<>();
-        for (NodeData child : getDeclaredNodes()) {
+        for (NodeData child : getEnclosingNodes()) {
             if (child.needsFactory()) {
                 nodeChildren.add(child);
             }
@@ -263,24 +228,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() {
@@ -290,7 +243,6 @@
             methods.add(specialization);
         }
 
-        methods.addAll(getSpecializationListeners());
         methods.addAll(getExecutableTypes());
         methods.addAll(getShortCircuits());
         if (getCasts() != null) {
@@ -394,6 +346,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()) {
@@ -436,13 +397,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));
             }
@@ -513,30 +473,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() {
@@ -547,43 +485,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() + "]";
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java	Tue Jan 07 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java	Tue Jan 07 18:52:32 2014 +0100
@@ -109,7 +109,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);
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Tue Jan 07 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Tue Jan 07 18:52:32 2014 +0100
@@ -34,14 +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.SpecializationData.*;
 import com.oracle.truffle.dsl.processor.template.*;
 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;
 
@@ -51,7 +52,6 @@
 
     @Override
     protected NodeData parse(Element element, AnnotationMirror mirror) {
-        assert element instanceof TypeElement;
         NodeData node = null;
         try {
             parsedNodes = new HashMap<>();
@@ -72,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();
@@ -105,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) {
@@ -139,153 +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);
-            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 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 TypeSignature(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<>();
@@ -303,109 +217,21 @@
             }
         }
         AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class);
+        String shortName = null;
         if (nodeInfoMirror != null) {
-            nodeData.setShortName(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));
-        nodeData.setChildExecutions(parseDefaultSignature(nodeData, elements));
-        nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
-
-        // resolveChildren invokes cyclic parsing.
-        parsedNodes.put(Utils.getQualifiedName(templateType), nodeData);
-        resolveChildren(nodeData);
-
-        return nodeData;
-    }
-
-    private List<NodeExecutionData> parseDefaultSignature(NodeData node, List<? extends Element> elements) {
-        if (node.getChildren() == 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 (!node.getChildren().isEmpty()) {
-            int lastIndex = node.getChildren().size() - 1;
-            hasVarArgs = node.getChildren().get(lastIndex).getCardinality() == Cardinality.MANY;
-            if (hasVarArgs) {
-                maxSignatureSize = lastIndex;
-            } else {
-                maxSignatureSize = node.getChildren().size();
-            }
+            shortName = Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName");
         }
 
-        // pre-parse specializations
-        for (ExecutableElement method : methods) {
-            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, Specialization.class);
-            if (mirror == null) {
-                continue;
-            }
+        List<NodeFieldData> fields = parseFields(typeHierarchy, elements);
+        List<NodeChildData> children = parseChildren(elements, typeHierarchy);
+        List<NodeExecutionData> executions = parseExecutions(children, elements);
 
-            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 < node.getChildren().size() ? currentArgumentCount : node.getChildren().size() - 1;
-                if (childIndex == -1) {
-                    continue;
-                }
-                if (!skipShortCircuit) {
-                    NodeChildData child = node.getChildren().get(childIndex);
-                    if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentCount - childIndex))) {
-                        skipShortCircuit = true;
-                        continue;
-                    }
-                } else {
-                    skipShortCircuit = false;
-                }
+        NodeData nodeData = new NodeData(templateType, shortName, typeSystem, children, executions, fields, assumptionsList, polymorphicLimit);
+        nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
 
-                currentArgumentCount++;
-            }
-            maxSignatureSize = Math.max(maxSignatureSize, currentArgumentCount);
-        }
+        parsedNodes.put(Utils.getQualifiedName(templateType), nodeData);
 
-        List<NodeExecutionData> executions = new ArrayList<>();
-        for (int i = 0; i < maxSignatureSize; i++) {
-            int childIndex = i;
-            boolean varArg = false;
-            if (childIndex >= node.getChildren().size() - 1) {
-                if (hasVarArgs) {
-                    childIndex = node.getChildren().size() - 1;
-                    varArg = hasVarArgs;
-                } else if (childIndex >= node.getChildren().size()) {
-                    break;
-                }
-            }
-            int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1;
-            NodeChildData child = node.getChildren().get(childIndex);
-            boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, varArgsIndex));
-            executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit));
-        }
-        return executions;
+        return nodeData;
     }
 
     private List<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) {
@@ -452,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);
@@ -498,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();
@@ -506,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) {
@@ -533,11 +333,13 @@
 
                 Element getter = findGetter(elements, name, childType);
 
-                NodeChildData nodeChild = new NodeChildData(parent, type, childMirror, name, childType, originalChildType, getter, cardinality);
+                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;
                 }
@@ -599,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;
             }
@@ -758,199 +589,15 @@
             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 specialization = specializations.get(0);
-        GenericParser parser = new GenericParser(context, node);
-        MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null);
-        specification.getImplicitRequiredTypes().clear();
-
-        List<TypeMirror> parameterTypes = new ArrayList<>();
-        int signatureIndex = 1;
-        for (ParameterSpec spec : specification.getRequired()) {
-            parameterTypes.add(createGenericType(spec, specializations, signatureIndex));
-            if (spec.isSignature()) {
-                signatureIndex++;
-            }
-        }
-        TypeMirror returnType = createGenericType(specification.getReturnType(), specializations, 0);
-        return parser.create("Generic", null, null, returnType, parameterTypes);
-    }
-
-    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 && !executable.hasUnexpectedValue(context)) {
-                    genericType = types.iterator().next();
-                }
-            }
-            if (genericType == null) {
-                genericType = child.findAnyGenericExecutableType(context).getType();
-            }
-            return genericType.getPrimitiveType();
-        }
     }
 
-    private void assignShortCircuitsToSpecializations(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;
-        }
-
-        List<SpecializationData> specializations = new ArrayList<>();
-        specializations.addAll(node.getSpecializations());
-        specializations.addAll(node.getPolymorphicSpecializations());
-
-        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 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<>();
@@ -1058,25 +705,370 @@
         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;
+        }
 
-        verifyMissingAbstractMethods(nodeData, elements);
+        List<SpecializationData> generics = new ArrayList<>();
+        for (SpecializationData spec : node.getSpecializations()) {
+            if (spec.isGeneric()) {
+                generics.add(spec);
+            }
+        }
+
+        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) {
+        SpecializationData specialization = node.getSpecializations().get(0);
+        GenericParser parser = new GenericParser(context, node);
+        MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null);
+        specification.getImplicitRequiredTypes().clear();
+
+        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);
+        return parser.create("Generic", null, null, returnType, parameterTypes);
+    }
 
-        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 && !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) {
@@ -1087,7 +1079,6 @@
         }
 
         List<Element> elements = new ArrayList<>(originalElements);
-
         Set<Element> unusedElements = new HashSet<>(elements);
         for (TemplateMethod method : nodeData.getAllTemplateMethods()) {
             unusedElements.remove(method.getMethod());
@@ -1112,6 +1103,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.
@@ -1152,104 +1170,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);
@@ -1289,61 +1209,13 @@
         return null;
     }
 
-    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;
+    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/SpecializationData.java	Tue Jan 07 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java	Tue Jan 07 18:52:32 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
@@ -141,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()) {
@@ -160,10 +156,6 @@
         return node;
     }
 
-    public void setNode(NodeData node) {
-        this.node = node;
-    }
-
     public void setGuards(List<GuardData> guards) {
         this.guards = guards;
     }
@@ -177,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() {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.java	Tue Jan 07 12:22:47 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 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java	Tue Jan 07 18:52:32 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/TemplateMethod.java	Tue Jan 07 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java	Tue Jan 07 18:52:32 2014 +0100
@@ -211,12 +211,10 @@
         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;
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java	Tue Jan 07 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java	Tue Jan 07 18:52:32 2014 +0100
@@ -31,7 +31,6 @@
 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.typesystem.*;
 
@@ -141,11 +140,6 @@
         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()) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateParser.java	Tue Jan 07 12:22:47 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/TypeSystemParser.java	Tue Jan 07 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java	Tue Jan 07 18:52:32 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()) {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java	Tue Jan 07 12:22:47 2014 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java	Tue Jan 07 18:52:32 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.
  */