changeset 7502:6343a09b2ec1

Codegen operation generation is inferred from the node type hierarchy.
author Christian Humer <christian.humer@gmail.com>
date Fri, 18 Jan 2013 13:28:12 +0100
parents 0f8c6dbf68be
children 31da1716950f
files graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ExecuteChildren.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Operation.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationGuard.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystemReference.java graal/com.oracle.truffle.codegen.processor/src/META-INF/services/javax.annotation.processing.Processor graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AnnotationProcessor.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ProcessorContext.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableExecutableElement.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeCompilationUnit.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeElement.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JDTCompiler.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JavaCCompiler.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationGuardData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationThrowsData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/GenericParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationCodeGenerator.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationFieldData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationMethodParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/ShortCircuitData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/ShortCircuitParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationGuardData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationListenerParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationThrowsData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CodeElementFactory.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CompilationUnitFactory.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java
diffstat 66 files changed, 3552 insertions(+), 2825 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ExecuteChildren.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,33 @@
+/*
+ * 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.codegen;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+public @interface ExecuteChildren {
+
+    String[] value();
+
+}
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Operation.java	Thu Jan 17 17:21:16 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +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.codegen;
-
-import java.lang.annotation.*;
-import com.oracle.truffle.api.nodes.*;
-
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE})
-public @interface Operation {
-
-    Class< ? > typeSystem();
-
-    Class<? extends Node> baseClass() default Node.class;
-
-    String[] values() default {};
-
-    String[] shortCircuitValues() default {};
-
-}
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationGuard.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationGuard.java	Fri Jan 18 13:28:12 2013 +0100
@@ -33,7 +33,7 @@
 
     /**
      * Specifies the name of the guard method annotated by {@link GuardCheck} specified as method in the
-     * {@link TypeSystem} or {@link Operation} class.
+     * {@link TypeSystem} class.
      */
     String methodName();
 
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java	Fri Jan 18 13:28:12 2013 +0100
@@ -24,8 +24,6 @@
 
 import java.lang.annotation.*;
 
-import com.oracle.truffle.api.nodes.*;
-
 /**
  * <p>
  * Annotates a type system class that represents type information for a node. Generates code for converting and managing
@@ -72,19 +70,6 @@
     /**
      * Sets the types contained by this type system. The order of types also determines the order of specialization.
      */
-    Class[] types();
-
-    /**
-     * Specifies whether the node base class has an executeVoid method or not. Operations derived from this type system
-     * will automatically implement executeVoid for all generated nodes. Defaults to false.
-     */
-    boolean hasVoid() default false;
-
-    /**
-     * Specifies the node base class used for generated code that uses this type system. The node base class must extend
-     * {@link Node} and provide a public non-final method <code>${type} execute${typeName}(VirtualFrame)</code> for all
-     * types specified in the types attribute.
-     */
-    Class< ? extends Node> nodeBaseClass();
+    Class[] value();
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystemReference.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,33 @@
+/*
+ * 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.codegen;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+public @interface TypeSystemReference {
+
+    Class<?> value();
+
+}
--- a/graal/com.oracle.truffle.codegen.processor/src/META-INF/services/javax.annotation.processing.Processor	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/META-INF/services/javax.annotation.processing.Processor	Fri Jan 18 13:28:12 2013 +0100
@@ -1,1 +1,1 @@
-com.oracle.truffle.codegen.processor.TruffleProcessor
+com.oracle.truffle.codegen.processor.TruffleProcessor
\ No newline at end of file
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -23,6 +23,7 @@
 package com.oracle.truffle.codegen.processor;
 
 import java.lang.annotation.*;
+import java.util.*;
 
 import javax.annotation.processing.*;
 import javax.lang.model.element.*;
@@ -49,7 +50,11 @@
     public final M parse(RoundEnvironment env, Element element) {
         this.roundEnv = env;
         try {
-            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType());
+            AnnotationMirror mirror = null;
+            if (getAnnotationType() != null) {
+                mirror = Utils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType());
+            }
+
             if (!context.getTruffleTypes().verify(context, element, mirror)) {
                 return null;
             }
@@ -60,7 +65,23 @@
     }
 
     protected abstract M parse(Element element, AnnotationMirror mirror);
-
     public abstract Class< ? extends Annotation> getAnnotationType();
 
+    public boolean isDelegateToRootDeclaredType() {
+        return false;
+    }
+
+    public List<Class<? extends Annotation>> getAllAnnotationTypes() {
+        List<Class<? extends Annotation>> list = new ArrayList<>();
+        if (getAnnotationType() != null) {
+            list.add(getAnnotationType());
+        }
+        list.addAll(getTypeDelegatedAnnotationTypes());
+        return list;
+    }
+
+    public List<Class<? extends Annotation>> getTypeDelegatedAnnotationTypes() {
+        return Collections.emptyList();
+    }
+
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AnnotationProcessor.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AnnotationProcessor.java	Fri Jan 18 13:28:12 2013 +0100
@@ -84,7 +84,7 @@
             context.registerTemplate(type, model);
 
             if (model != null) {
-                CodeCompilationUnit unit = (CodeCompilationUnit) factory.process(model);
+                CodeCompilationUnit unit = factory.process(null, model);
                 unit.setGeneratorAnnotationMirror(model.getTemplateTypeAnnotation());
                 unit.setGeneratorElement(model.getTemplateType());
 
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java	Fri Jan 18 13:28:12 2013 +0100
@@ -51,6 +51,10 @@
         message(Kind.ERROR, element, null, null, format, args);
     }
 
+    public void error(String format, Object... args) {
+        message(Kind.ERROR, null, null, null, format, args);
+    }
+
     public void error(Element element, AnnotationMirror mirror, String format, Object... args) {
         message(Kind.ERROR, element, mirror, null, format, args);
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ProcessorContext.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ProcessorContext.java	Fri Jan 18 13:28:12 2013 +0100
@@ -45,18 +45,16 @@
 
     private final ProcessCallback callback;
     private final Log log;
-    private TruffleTypes truffleTypes;
+    private final TruffleTypes truffleTypes;
 
     public ProcessorContext(ProcessingEnvironment env, ProcessCallback callback) {
         this.environment = env;
         this.callback = callback;
         this.log = new Log(environment);
+        this.truffleTypes = new TruffleTypes(this);
     }
 
     public TruffleTypes getTruffleTypes() {
-        if (truffleTypes == null) {
-            truffleTypes = new TruffleTypes(this);
-        }
         return truffleTypes;
     }
 
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java	Fri Jan 18 13:28:12 2013 +0100
@@ -30,7 +30,7 @@
 import javax.lang.model.element.*;
 
 import com.oracle.truffle.codegen.processor.ProcessorContext.ProcessCallback;
-import com.oracle.truffle.codegen.processor.operation.*;
+import com.oracle.truffle.codegen.processor.node.*;
 import com.oracle.truffle.codegen.processor.typesystem.*;
 
 /**
@@ -53,15 +53,30 @@
         return false;
     }
 
-    @SuppressWarnings("unchecked")
     private void processImpl(RoundEnvironment env) {
         this.round = env;
         // TODO run verifications that other annotations are not processed out of scope of the operation or typelattice.
         try {
             for (AnnotationProcessor generator : getGenerators()) {
-                for (Element e : env.getElementsAnnotatedWith(generator.getParser().getAnnotationType())) {
-                    processElement(env, generator, e, false);
+                AbstractParser<?> parser = generator.getParser();
+                if (parser.getAnnotationType() != null) {
+                    for (Element e : env.getElementsAnnotatedWith(parser.getAnnotationType())) {
+                        processElement(env, generator, e, false);
+                    }
                 }
+
+                for (Class<? extends Annotation> annotationType : parser.getTypeDelegatedAnnotationTypes()) {
+                    for (Element e : env.getElementsAnnotatedWith(annotationType)) {
+                        TypeElement processedType;
+                        if (parser.isDelegateToRootDeclaredType()) {
+                            processedType = Utils.findRootEnclosingType(e);
+                        } else {
+                            processedType = Utils.findNearestEnclosingType(e);
+                        }
+                        processElement(env, generator, processedType, false);
+                    }
+                }
+
             }
         } finally {
             this.round = null;
@@ -85,9 +100,12 @@
     @Override
     public void callback(TypeElement template) {
         for (AnnotationProcessor generator : generators) {
-            Annotation annotation = template.getAnnotation(generator.getParser().getAnnotationType());
-            if (annotation != null) {
-                processElement(round, generator, template, true);
+            Class annotationType = generator.getParser().getAnnotationType();
+            if (annotationType != null) {
+                Annotation annotation = template.getAnnotation(annotationType);
+                if (annotation != null) {
+                    processElement(round, generator, template, true);
+                }
             }
         }
     }
@@ -96,7 +114,12 @@
     public Set<String> getSupportedAnnotationTypes() {
         Set<String> annotations = new HashSet<>();
         for (AnnotationProcessor< ? > generator : getGenerators()) {
-            annotations.add(generator.getParser().getAnnotationType().getCanonicalName());
+            for (Class<? extends Annotation> annotationClass : generator.getParser().getAllAnnotationTypes()) {
+                if (annotationClass == null) {
+                    throw new NullPointerException("class is null");
+                }
+                annotations.add(annotationClass.getCanonicalName());
+            }
         }
         return annotations;
     }
@@ -105,7 +128,7 @@
         if (generators == null && processingEnv != null) {
             generators = new ArrayList<>();
             generators.add(new AnnotationProcessor<>(getContext(), new TypeSystemParser(getContext()), new TypeSystemCodeGenerator(getContext())));
-            generators.add(new AnnotationProcessor<>(getContext(), new OperationParser(getContext()), new OperationCodeGenerator(getContext())));
+            generators.add(new AnnotationProcessor<>(getContext(), new NodeParser(getContext()), new NodeCodeGenerator(getContext())));
         }
         return generators;
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Fri Jan 18 13:28:12 2013 +0100
@@ -63,6 +63,11 @@
         return result;
     }
 
+    public static String getReadableSignature(ExecutableElement method) {
+        // TODO toString does not guarantee a good signature
+        return method.toString();
+    }
+
     public static boolean hasError(TypeMirror mirror) {
         switch (mirror.getKind()) {
             case BOOLEAN:
@@ -243,13 +248,41 @@
         return null;
     }
 
-    public static TypeElement findEnclosingType(Element element) {
-        Element enclosing = element.getEnclosingElement();
-        while (enclosing.getKind() != ElementKind.CLASS && enclosing.getKind() != ElementKind.ENUM && enclosing.getKind() != ElementKind.INTERFACE) {
-            enclosing = element.getEnclosingElement();
+    public static TypeElement findRootEnclosingType(Element element) {
+        List<Element> elements = getElementHierarchy(element);
+
+        for (int i = elements.size() - 1; i >= 0; i--) {
+            if (elements.get(i).getKind().isClass()) {
+                return (TypeElement) elements.get(i);
+            }
         }
 
-        return (TypeElement) enclosing;
+        return null;
+    }
+
+    private static List<Element> getElementHierarchy(Element e) {
+        List<Element> elements = new ArrayList<>();
+        elements.add(e);
+
+        Element enclosing = e.getEnclosingElement();
+        while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) {
+            elements.add(enclosing);
+            enclosing = enclosing.getEnclosingElement();
+        }
+        if (enclosing != null) {
+            elements.add(enclosing);
+        }
+        return elements;
+    }
+
+    public static TypeElement findNearestEnclosingType(Element element) {
+        List<Element> elements = getElementHierarchy(element);
+        for (Element e : elements) {
+            if (e.getKind().isClass()) {
+                return (TypeElement) e;
+            }
+        }
+        return null;
     }
 
     public static List<TypeElement> getSuperTypes(TypeElement element) {
@@ -391,7 +424,7 @@
     }
 
     public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List< ? extends AnnotationMirror> mirrors, Class< ? > annotationClass) {
-        TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getName());
+        TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName());
         for (AnnotationMirror mirror : mirrors) {
             DeclaredType annotationType = mirror.getAnnotationType();
             TypeElement actualAnnotationType = (TypeElement) annotationType.asElement();
@@ -403,11 +436,13 @@
     }
 
     private static PackageElement findPackageElement(Element type) {
-        Element searchType = type;
-        while (searchType.getEnclosingElement() != null && searchType.getEnclosingElement().getKind() != ElementKind.PACKAGE) {
-            searchType = type.getEnclosingElement();
+        List<Element> hierarchy = getElementHierarchy(type);
+        for (Element element : hierarchy) {
+            if (element.getKind() == ElementKind.PACKAGE) {
+                return (PackageElement) element;
+            }
         }
-        return (PackageElement) searchType.getEnclosingElement();
+        return null;
     }
 
     public static String firstLetterUpperCase(String name) {
@@ -530,6 +565,19 @@
         return false;
     }
 
+    public static Modifier getVisibility(Set<Modifier> modifier) {
+        for (Modifier mod : modifier) {
+            if (mod == Modifier.PUBLIC) {
+                return mod;
+            } else if (mod == Modifier.PRIVATE) {
+                return mod;
+            } else if (mod == Modifier.PROTECTED) {
+                return mod;
+            }
+        }
+        return null;
+    }
+
     private static boolean isRuntimeException(TypeMirror type) {
         Set<String> typeSuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(type)));
         String typeName = getQualifiedName(type);
@@ -548,4 +596,13 @@
         return false;
     }
 
+    public static boolean isTopLevelClass(TypeMirror importType) {
+        TypeElement type = fromTypeMirror(importType);
+        if (type != null && type.getEnclosingElement() != null) {
+            return !type.getEnclosingElement().getKind().isClass();
+        }
+        return true;
+    }
+
+
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableExecutableElement.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableExecutableElement.java	Fri Jan 18 13:28:12 2013 +0100
@@ -31,7 +31,7 @@
     void setDefaultValue(AnnotationValue defaultValue);
 
     void addParameter(VariableElement parameter);
-    void removeParamter(VariableElement parameter);
+    void removeParameter(VariableElement parameter);
 
     void addThrownType(TypeMirror thrownType);
     void removeThrownType(TypeMirror thrownType);
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeCompilationUnit.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeCompilationUnit.java	Fri Jan 18 13:28:12 2013 +0100
@@ -50,8 +50,12 @@
 
     @Override
     public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        for (TypeElement type : getEnclosedElements()) {
-            type.accept(v, p);
+        for (Element type : getEnclosedElements()) {
+            if (type.getKind().isClass()) {
+                type.accept(v, p);
+            } else {
+                throw new ClassCastException(type.getClass().getName());
+            }
         }
         return null;
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java	Fri Jan 18 13:28:12 2013 +0100
@@ -119,9 +119,6 @@
     }
 
     void setEnclosingElement(Element parent) {
-        if (this.enclosingElement != null && parent != null) {
-            throw new IllegalStateException("Element already added to " + parent);
-        }
         this.enclosingElement = parent;
     }
 
@@ -161,7 +158,7 @@
             return writer;
         }
         public String getString() {
-            return new String(((CharArrayWriter) writer).toCharArray());
+            return new String(((CharArrayWriter) writer).toCharArray()).trim();
         }
 
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java	Fri Jan 18 13:28:12 2013 +0100
@@ -71,7 +71,11 @@
 
     @Override
     public ElementKind getKind() {
-        return ElementKind.METHOD;
+        if (getReturnType() == null) {
+            return ElementKind.CONSTRUCTOR;
+        } else {
+            return ElementKind.METHOD;
+        }
     }
 
     @Override
@@ -108,6 +112,7 @@
         CodeTreeBuilder builder = new CodeTreeBuilder();
         this.bodyTree = builder.getTree();
         this.bodyTree.setEnclosingElement(this);
+        this.body = null;
         return builder;
     }
 
@@ -147,10 +152,24 @@
     }
 
     @Override
-    public void removeParamter(VariableElement parameter) {
+    public void removeParameter(VariableElement parameter) {
         parameters.remove(parameter);
     }
 
+
+    public void removeParameter(String varName) {
+        VariableElement remove = null;
+        for (VariableElement var : getParameters()) {
+            if (var.getSimpleName().toString().equals(varName)) {
+                remove = var;
+                break;
+            }
+        }
+        if (remove != null) {
+            parameters.remove(remove);
+        }
+    }
+
     @Override
     public void addThrownType(TypeMirror thrownType) {
         throwables.add(thrownType);
@@ -181,7 +200,6 @@
         return v.visitExecutable(this, p);
     }
 
-
     public static CodeExecutableElement clone(ProcessingEnvironment env, ExecutableElement method) {
         CodeExecutableElement copy = new CodeExecutableElement(method.getReturnType(), method.getSimpleName().toString());
         for (TypeMirror thrownType : method.getThrownTypes()) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java	Fri Jan 18 13:28:12 2013 +0100
@@ -99,12 +99,10 @@
     public CodeTreeBuilder startStatement() {
         startGroup();
         registerCallBack(new EndCallback() {
-
             @Override
             public void beforeEnd() {
                 string(";").newLine();
             }
-
             @Override
             public void afterEnd() {
             }
@@ -137,7 +135,7 @@
     }
 
     public CodeTreeBuilder startStaticCall(ExecutableElement method) {
-        return startStaticCall(Utils.findEnclosingType(method).asType(), method.getSimpleName().toString());
+        return startStaticCall(Utils.findNearestEnclosingType(method).asType(), method.getSimpleName().toString());
     }
 
     public CodeTreeBuilder staticReference(TypeMirror type, String fieldName) {
@@ -317,7 +315,17 @@
     public CodeTreeBuilder startReturn() {
         ExecutableElement method = findMethod();
         if (method != null && Utils.isVoid(method.getReturnType())) {
-            startStatement();
+            startGroup();
+            registerCallBack(new EndCallback() {
+                @Override
+                public void beforeEnd() {
+                    string(";").newLine(); // complete statement to execute
+                }
+                @Override
+                public void afterEnd() {
+                    string("return").string(";").newLine(); // emit a return;
+                }
+            });
             return this;
         } else {
             return startStatement().string("return ");
@@ -471,7 +479,7 @@
         return statement("return");
     }
 
-    private ExecutableElement findMethod() {
+    public ExecutableElement findMethod() {
         Element element = currentElement;
         while (element != null && (element.getKind() != ElementKind.METHOD)) {
             element = element.getEnclosingElement();
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeElement.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeElement.java	Fri Jan 18 13:28:12 2013 +0100
@@ -182,6 +182,16 @@
         return ElementFilter.fieldsIn(getEnclosedElements());
     }
 
+    public ExecutableElement getMethod(String name) {
+        for (Element element : getEnclosedElements()) {
+            if (element.getKind() == ElementKind.METHOD
+                            && element.getSimpleName().toString().equals(name)) {
+               return (ExecutableElement) element;
+            }
+        }
+        return null;
+    }
+
     public List<ExecutableElement> getMethods() {
         return ElementFilter.methodsIn(getEnclosedElements());
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java	Fri Jan 18 13:28:12 2013 +0100
@@ -175,6 +175,10 @@
             writeEmptyLn();
         }
 
+        for (ExecutableElement method : ElementFilter.constructorsIn(e.getEnclosedElements())) {
+            method.accept(this, null);
+        }
+
         for (ExecutableElement method : getInstanceMethods(e)) {
             method.accept(this, null);
         }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java	Fri Jan 18 13:28:12 2013 +0100
@@ -182,7 +182,7 @@
                 continue; // java.lang is automatically imported
             }
 
-            if (importTypePackageName.equals(getPackageName(e))) {
+            if (importTypePackageName.equals(getPackageName(e)) && Utils.isTopLevelClass(importType)) {
                 continue; // same package name -> no import
             }
 
@@ -199,8 +199,8 @@
     }
 
     private static void collectInnerTypeImports(TypeElement e, Set<String> autoImportedTypes) {
+        autoImportedTypes.add(getQualifiedName(e));
         for (TypeElement innerClass : ElementFilter.typesIn(e.getEnclosedElements())) {
-            collectSuperTypeImports(innerClass, autoImportedTypes);
             collectInnerTypeImports(innerClass, autoImportedTypes);
         }
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JDTCompiler.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JDTCompiler.java	Fri Jan 18 13:28:12 2013 +0100
@@ -31,7 +31,7 @@
 
     public static boolean isValidElement(Element currentElement) {
         try {
-            Class<?> elementClass = Class.forName("org.eclipse.jdt.internal.compiler.apt.model.ElementImpl");
+            Class< ? > elementClass = Class.forName("org.eclipse.jdt.internal.compiler.apt.model.ElementImpl");
             return elementClass.isAssignableFrom(currentElement.getClass());
         } catch (ClassNotFoundException e) {
             return false;
@@ -48,10 +48,9 @@
             }
 
             /*
-            AbstractMethodDeclaration decl = ((MethodBinding)(((ElementImpl)method)._binding)).sourceMethod();
-            int bodyStart = decl.bodyStart;
-            int bodyEnd = decl.bodyEnd;
-            */
+             * AbstractMethodDeclaration decl = ((MethodBinding)(((ElementImpl)method)._binding)).sourceMethod(); int
+             * bodyStart = decl.bodyStart; int bodyEnd = decl.bodyEnd;
+             */
             Object decl = method(field(method, "_binding"), "sourceMethod");
             int bodyStart = (int) field(decl, "bodyStart");
             int bodyEnd = (int) field(decl, "bodyEnd");
@@ -66,22 +65,19 @@
         }
     }
 
-
     private static char[] getSource(Element element) throws Exception {
         /*
-        Binding binding = ((ElementImpl)element)._binding;
-        char[] source = null;
-        if (binding instanceof MethodBinding) {
-            source = ((MethodBinding) binding).sourceMethod().compilationResult.getCompilationUnit().getContents();
-        } else if (binding instanceof SourceTypeBinding) {
-            source = ((SourceTypeBinding)binding).scope.referenceContext.compilationResult.compilationUnit.getContents();
-        }
-        return source;
-        */
+         * Binding binding = ((ElementImpl)element)._binding; char[] source = null; if (binding instanceof
+         * MethodBinding) { source = ((MethodBinding)
+         * binding).sourceMethod().compilationResult.getCompilationUnit().getContents(); } else if (binding instanceof
+         * SourceTypeBinding) { source =
+         * ((SourceTypeBinding)binding).scope.referenceContext.compilationResult.compilationUnit.getContents(); } return
+         * source;
+         */
 
         Object binding = field(element, "_binding");
-        Class<?> methodBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.MethodBinding");
-        Class<?> referenceBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding");
+        Class< ? > methodBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.MethodBinding");
+        Class< ? > referenceBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding");
 
         char[] source = null;
         if (methodBindingClass.isAssignableFrom(binding.getClass())) {
@@ -96,7 +92,6 @@
         return source;
     }
 
-
     @Override
     public String getHeaderComment(ProcessingEnvironment env, Element type) {
         try {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JavaCCompiler.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JavaCCompiler.java	Fri Jan 18 13:28:12 2013 +0100
@@ -90,6 +90,4 @@
         }
     }
 
-
-
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -46,11 +46,11 @@
         this.extensionContext = new ExtensionContextImpl(context.getEnvironment(), null, factory);
     }
 
-    public List<WritableElement> parseAll(TypeElement typeElement) {
+    public List<WritableElement> parseAll(TypeElement typeElement, List<? extends Element> elements) {
         List<WritableElement> generatedMethods = new ArrayList<>();
         parseElement(generatedMethods, typeElement);
 
-        List<? extends ExecutableElement> methods = ElementFilter.methodsIn(typeElement.getEnclosedElements());
+        List<? extends ExecutableElement> methods = ElementFilter.methodsIn(elements);
         for (ExecutableElement method : methods) {
             for (VariableElement var : method.getParameters()) {
                 parseElement(generatedMethods, var);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,76 @@
+/*
+ * 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.codegen.processor.node;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.typesystem.*;
+
+
+public class ExecutableTypeData extends TemplateMethod {
+
+    private final TypeSystemData typeSystem;
+    private final TypeData type;
+
+    public ExecutableTypeData(TemplateMethod method, TypeSystemData typeSystem, TypeData type) {
+        super(method);
+        this.typeSystem = typeSystem;
+        this.type = type;
+    }
+
+    public TypeData getType() {
+        return type;
+    }
+
+    public TypeSystemData getTypeSystem() {
+        return typeSystem;
+    }
+
+    public boolean hasFrame() {
+        return getMethod().getParameters().size() > 0;
+    }
+
+    public boolean hasUnexpectedValue(ProcessorContext context) {
+        return Utils.canThrowType(getMethod().getThrownTypes(), context.getTruffleTypes().getUnexpectedValueException());
+    }
+
+    public boolean isFinal() {
+        return getMethod().getModifiers().contains(Modifier.FINAL);
+    }
+
+    @Override
+    public int hashCode() {
+        return type.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof ExecutableTypeData) {
+            return type.equals(((ExecutableTypeData) obj).type);
+        }
+        return super.equals(obj);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,78 @@
+/*
+ * 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.codegen.processor.node;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
+import com.oracle.truffle.codegen.processor.typesystem.*;
+
+public class ExecutableTypeMethodParser extends MethodParser<ExecutableTypeData> {
+
+    public ExecutableTypeMethodParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+        setEmitErrors(false);
+        setParseNullOnError(false);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        List<TypeMirror> types = new ArrayList<>();
+        types.addAll(Arrays.asList(getNode().getTypeSystem().getPrimitiveTypeMirrors()));
+        types.add(getContext().getType(void.class));
+
+        ParameterSpec returnTypeSpec = new ParameterSpec("executedValue", types.toArray(new TypeMirror[types.size()]),
+                        getNode().getTypeSystem().getGenericType(), false, Cardinality.ONE);
+
+        List<ParameterSpec> parameters = new ArrayList<>();
+        parameters.add(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), true));
+        return new MethodSpec(returnTypeSpec, parameters);
+    }
+
+    @Override
+    public final boolean isParsable(ExecutableElement method) {
+        boolean parsable = method.getSimpleName().toString().startsWith("execute");
+        return parsable;
+    }
+
+    @Override
+    public ExecutableTypeData create(TemplateMethod method) {
+        TypeData resolvedType = method.getReturnType().getActualTypeData(getNode().getTypeSystem());
+        if (resolvedType == null) {
+            return null;
+        }
+        return new ExecutableTypeData(method, getNode().getTypeSystem(), resolvedType);
+    }
+
+    @Override
+    public Class< ? extends Annotation> getAnnotationType() {
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,64 @@
+/*
+ * 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.codegen.processor.node;
+
+import java.lang.annotation.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+
+public class GenericParser extends MethodParser<SpecializationData> {
+
+    public GenericParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        return createDefaultMethodSpec(null);
+    }
+
+    @Override
+    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData) {
+        return new ParameterSpec(valueName, nodeData.findGenericExecutableType(getContext()).getType().getPrimitiveType(), false);
+    }
+
+    @Override
+    protected ParameterSpec createReturnParameterSpec() {
+        return super.createValueParameterSpec("returnValue", getNode());
+    }
+
+    @Override
+    public SpecializationData create(TemplateMethod method) {
+        return new SpecializationData(method, true, false);
+    }
+
+    @Override
+    public Class< ? extends Annotation> getAnnotationType() {
+        return Generic.class;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,93 @@
+/*
+ * 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.codegen.processor.node;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
+
+
+public abstract class MethodParser<E extends TemplateMethod> extends TemplateMethodParser<NodeData, E>{
+
+    public MethodParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+    }
+
+    public NodeData getNode() {
+        return template;
+    }
+
+
+    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData) {
+        return new ParameterSpec(valueName, nodeData, false, Cardinality.ONE);
+    }
+
+    protected ParameterSpec createReturnParameterSpec() {
+        return createValueParameterSpec("operation", getNode());
+    }
+
+    @Override
+    public boolean isParsable(ExecutableElement method) {
+        return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
+    }
+
+    protected final MethodSpec createDefaultMethodSpec(String shortCircuitName) {
+        List<ParameterSpec> defaultParameters = new ArrayList<>();
+        ParameterSpec frameSpec = new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), true);
+        defaultParameters.add(frameSpec);
+
+        for (NodeFieldData field : getNode().getFields()) {
+            if (field.getExecutionKind() == ExecutionKind.IGNORE) {
+                continue;
+            }
+
+            if (field.getExecutionKind() == ExecutionKind.DEFAULT) {
+                defaultParameters.add(createValueParameterSpec(field.getName(), field.getNodeData()));
+            } else if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) {
+                String valueName = field.getName();
+                if (shortCircuitName != null && valueName.equals(shortCircuitName)) {
+                    break;
+                }
+
+                defaultParameters.add(new ParameterSpec(shortCircuitValueName(valueName),
+                                getContext().getType(boolean.class), false));
+
+                defaultParameters.add(createValueParameterSpec(valueName, field.getNodeData()));
+            } else {
+                assert false;
+            }
+        }
+
+        return new MethodSpec(createReturnParameterSpec(), defaultParameters);
+    }
+
+    private static String shortCircuitValueName(String valueName) {
+        return "has" + Utils.firstLetterUpperCase(valueName);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,866 @@
+/*
+ * 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.codegen.processor.node;
+
+import static com.oracle.truffle.codegen.processor.Utils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.ast.*;
+import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.typesystem.*;
+
+
+public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> {
+
+    private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode";
+
+    public NodeCodeGenerator(ProcessorContext context) {
+        super(context);
+    }
+
+    private TypeMirror getUnexpectedValueException() {
+        return getContext().getTruffleTypes().getUnexpectedValueException();
+    }
+
+    private static String factoryClassName(NodeData node) {
+        return nodeClassName(node) + "Factory";
+    }
+
+    private static String nodeClassName(NodeData node) {
+        return Utils.getSimpleName(node.getTemplateType().asType());
+    }
+
+    private static String nodeClassName(SpecializationData specialization) {
+        String name = "";
+        if (specialization.getNode().getSpecializations().length > 1) {
+            name = specialization.getMethodName();
+            if (name.startsWith("do")) {
+                name = name.substring(2);
+            }
+        }
+        name += nodeClassName(specialization.getNode());
+        if (name.equals(Utils.getSimpleName(specialization.getNode().getNodeType()))
+                        || name.equals(Utils.getSimpleName(specialization.getNode().getTemplateType()))) {
+            name = name + "Impl";
+        }
+
+        return name;
+    }
+
+    private static String valueName(NodeFieldData field) {
+        return field.getName() + "Value";
+    }
+
+    private static String valueName(TemplateMethod method, ActualParameter param) {
+        NodeData node = (NodeData) method.getTemplate();
+        NodeFieldData field = node.findField(param.getSpecification().getName());
+        if (field != null) {
+            return valueName(field);
+        } else {
+            return param.getSpecification().getName();
+        }
+    }
+
+    private void addValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame) {
+        if (forceFrame) {
+            method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frame"));
+        }
+        for (ActualParameter parameter : specialization.getParameters()) {
+            ParameterSpec spec = parameter.getSpecification();
+            if (forceFrame && spec.getName().equals("frame")) {
+                continue;
+            }
+            method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(specialization, parameter)));
+        }
+    }
+
+    private static void addValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame) {
+        if (forceFrame) {
+            builder.string("frame");
+        }
+        for (ActualParameter parameter : specialization.getParameters()) {
+            ParameterSpec spec = parameter.getSpecification();
+            if (forceFrame && spec.getName().equals("frame")) {
+                continue;
+            }
+
+            if (unexpectedValueName != null && spec.getName().equals(unexpectedValueName)) {
+                builder.string("ex.getResult()");
+            } else {
+                builder.string(valueName(specialization, parameter));
+            }
+        }
+    }
+
+    private static void addValueParameterNamesWithCasts(ProcessorContext context, CodeTreeBuilder body, SpecializationData specialization) {
+        for (ActualParameter param : specialization.getParameters()) {
+            TypeData typeData = param.getActualTypeData(specialization.getNode().getTypeSystem());
+            if (typeData == null || typeData.isGeneric()) {
+                body.string(valueName(specialization, param));
+            } else {
+                String methodName = TypeSystemCodeGenerator.asTypeMethodName(typeData);
+                startCallTypeSystemMethod(context, body, specialization.getNode(), methodName);
+                body.string(valueName(specialization, param));
+                body.end().end();
+            }
+        }
+    }
+
+    private static String genClassName(Template operation) {
+        return getSimpleName(operation.getTemplateType()) + "Gen";
+    }
+
+    private static void startCallOperationMethod(CodeTreeBuilder body, TemplateMethod method) {
+        body.startGroup();
+        if (body.findMethod().getModifiers().contains(STATIC)) {
+            body.string(THIS_NODE_LOCAL_VAR_NAME);
+        } else {
+            body.string("super");
+        }
+        body.string(".");
+        body.startCall(method.getMethodName());
+    }
+
+    private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body,  NodeData node, String methodName) {
+        VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, node.getTypeSystem());
+        assert singleton != null;
+
+        body.startGroup();
+        body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString());
+        body.string(".").startCall(methodName);
+    }
+
+    private static void emitGuards(ProcessorContext context, CodeTreeBuilder body, String prefix, SpecializationData specialization, boolean onSpecialization, boolean needsCast) {
+        TypeSystemData typeSystem = specialization.getNode().getTypeSystem();
+        // Implict guards based on method signature
+        String andOperator = prefix;
+        for (NodeFieldData field : specialization.getNode().getFields()) {
+            ActualParameter param = specialization.findParameter(field.getName());
+            TypeData type = param.getActualTypeData(typeSystem);
+            if (type == null || type.isGeneric()) {
+                continue;
+            }
+
+            body.string(andOperator);
+            startCallTypeSystemMethod(context, body, specialization.getNode(),
+                            TypeSystemCodeGenerator.isTypeMethodName(type));
+            body.string(valueName(specialization, param));
+            body.end().end(); // call
+            andOperator = " && ";
+        }
+
+        if (specialization.getGuards().length > 0) {
+            // Explicitly specified guards
+            for (SpecializationGuardData guard : specialization.getGuards()) {
+                if ((guard.isOnSpecialization() && onSpecialization)
+                                || (guard.isOnExecution() && !onSpecialization)) {
+                    body.string(andOperator);
+
+                    startCallOperationMethod(body, guard.getGuardDeclaration());
+
+                    if (needsCast) {
+                        addValueParameterNamesWithCasts(context, body, specialization);
+                    } else {
+                        addValueParameterNames(body, specialization, null, false);
+                    }
+                    body.end().end(); // call
+                    andOperator = " && ";
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void createChildren(NodeData node) {
+        Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>();
+        if (node.getDeclaredChildren() != null && !node.getDeclaredChildren().isEmpty()) {
+            for (NodeData nodeChild : node.getDeclaredChildren()) {
+                NodeCodeGenerator generator = new NodeCodeGenerator(getContext());
+                childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements());
+            }
+        }
+
+        if (node.getExtensionElements() != null && !node.getExtensionElements().isEmpty()) {
+            NodeGenFactory factory = new NodeGenFactory(context);
+            add(factory, node);
+        }
+
+        if (node.getSpecializations() == null) {
+            return;
+        }
+
+        if (node.needsFactory() || childTypes.size() > 0) {
+            add(new NodeFactoryFactory(context, childTypes), node);
+        }
+    }
+
+    private class NodeGenFactory extends ClassElementFactory<NodeData> {
+
+        public NodeGenFactory(ProcessorContext context) {
+            super(context);
+        }
+
+        @Override
+        protected CodeTypeElement create(NodeData node) {
+            CodeTypeElement clazz = createClass(node, modifiers(PUBLIC, ABSTRACT), genClassName(node), node.getTemplateType().asType(), false);
+
+            for (ExecutableElement executable : ElementFilter.constructorsIn(node.getTemplateType().getEnclosedElements())) {
+                CodeExecutableElement superConstructor = createSuperConstructor(clazz, executable);
+
+                if (superConstructor != null) {
+                    if (superConstructor.getParameters().size() == 1
+                                    && Utils.typeEquals(superConstructor.getParameters().get(0).asType(), node.getTemplateType().asType())) {
+                        String originalName = superConstructor.getParameters().get(0).getSimpleName().toString();
+                        superConstructor.getParameters().clear();
+                        superConstructor.getParameters().add(new CodeVariableElement(clazz.asType(), originalName));
+                    }
+                    clazz.add(superConstructor);
+                }
+            }
+
+            if (node.getExtensionElements() != null) {
+                clazz.getEnclosedElements().addAll(node.getExtensionElements());
+            }
+
+            node.setNodeType(clazz.asType());
+
+            return clazz;
+        }
+
+    }
+
+    private class NodeFactoryFactory extends ClassElementFactory<NodeData> {
+
+        private final Map<NodeData, List<TypeElement>> childTypes;
+
+        public NodeFactoryFactory(ProcessorContext context, Map<NodeData, List<TypeElement>> childElements) {
+            super(context);
+            this.childTypes = childElements;
+        }
+
+        @Override
+        protected CodeTypeElement create(NodeData node) {
+            Modifier visibility = Utils.getVisibility(node.getTemplateType().getModifiers());
+            CodeTypeElement clazz = createClass(node, modifiers(), factoryClassName(node), null, false);
+            if (visibility != null) {
+                clazz.getModifiers().add(visibility);
+            }
+            clazz.getModifiers().add(Modifier.FINAL);
+            clazz.add(createConstructorUsingFields(modifiers(PRIVATE), clazz));
+            return clazz;
+        }
+
+        @Override
+        protected void createChildren(NodeData node) {
+            CodeTypeElement clazz = getElement();
+
+            Modifier createVisibility = Utils.getVisibility(clazz.getModifiers());
+
+            if (node.needsFactory()) {
+                createFactoryMethods(node, clazz, createVisibility);
+
+                if (node.getSpecializations().length > 1) {
+                    clazz.add(createCreateSpecializedMethod(node, createVisibility));
+                }
+
+                if (node.needsRewrites(getContext())) {
+                    clazz.add(createSpecializeMethod(node));
+                    clazz.add(createGeneratedGenericMethod(node));
+                }
+
+                for (SpecializationData specialization : node.getSpecializations()) {
+                    add(new SpecializedNodeFactory(context), specialization);
+                }
+            }
+
+            for (NodeData childNode : childTypes.keySet()) {
+                if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) {
+                    continue;
+                }
+
+                for (TypeElement type : childTypes.get(childNode)) {
+                    Set<Modifier> typeModifiers = ((CodeTypeElement) type).getModifiers();
+                    Modifier visibility = Utils.getVisibility(type.getModifiers());
+                    typeModifiers.clear();
+                    if (visibility != null) {
+                        typeModifiers.add(visibility);
+                    }
+
+                    typeModifiers.add(Modifier.STATIC);
+                    typeModifiers.add(Modifier.FINAL);
+                    clazz.add(type);
+                }
+            }
+        }
+
+        private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) {
+            for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(node.getNodeType()).getEnclosedElements())) {
+                if (constructor.getModifiers().contains(PRIVATE)) {
+                    continue;
+                }
+
+                // skip node rewrite constructor
+                if (constructor.getParameters().size() == 1
+                                && typeEquals(constructor.getParameters().get(0).asType(), node.getNodeType())) {
+                    continue;
+                }
+
+                clazz.add(createCreateMethod(node, createVisibility, constructor));
+            }
+        }
+
+        private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) {
+            CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), constructor);
+            method.setSimpleName(CodeNames.of("create"));
+            method.getModifiers().clear();
+            if (visibility != null) {
+                method.getModifiers().add(visibility);
+            }
+            method.getModifiers().add(Modifier.STATIC);
+            method.setReturnType(node.getNodeType());
+
+            CodeTreeBuilder body = method.createBuilder();
+            body.startReturn();
+            if (node.getSpecializations().length == 0) {
+                body.null_();
+            } else {
+                body.startNew(nodeClassName(node.getSpecializations()[0]));
+                for (VariableElement var : method.getParameters()) {
+                    body.string(var.getSimpleName().toString());
+                }
+                body.end();
+            }
+            body.end();
+            return method;
+        }
+
+        private CodeExecutableElement createCreateSpecializedMethod(NodeData node, Modifier visibility) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(), node.getNodeType(), "createSpecialized");
+            if (visibility != null) {
+                method.getModifiers().add(visibility);
+            }
+            method.getModifiers().add(Modifier.STATIC);
+
+            method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
+            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "specializationClass"));
+
+            CodeTreeBuilder body = method.createBuilder();
+            boolean first = true;
+            for (TypeData type : node.getTypeSystem().getTypes()) {
+                SpecializationData specialization = node.findUniqueSpecialization(type);
+                if (specialization != null && !type.isGeneric()) {
+                    if (first) {
+                        body.startIf();
+                        first = false;
+                    } else {
+                        body.startElseIf();
+                    }
+                    body.string("specializationClass == ").type(type.getBoxedType()).string(".class").end().startBlock();
+                    body.startReturn().startNew(nodeClassName(specialization));
+                    body.string(THIS_NODE_LOCAL_VAR_NAME);
+                    body.end().end(); // new, return
+
+                    body.end(); // if
+                }
+            }
+            body.startReturn().startNew(nodeClassName(node.getGenericSpecialization()));
+            body.string(THIS_NODE_LOCAL_VAR_NAME);
+            body.end().end();
+            return method;
+        }
+
+        private CodeExecutableElement createSpecializeMethod(NodeData node) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), node.getNodeType(), "specialize");
+            method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
+            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState"));
+            addValueParameters(method, node.getGenericSpecialization(), false);
+
+            CodeTreeBuilder body = method.createBuilder();
+            body.startStatement().string("boolean allowed = (minimumState == ").string(nodeClassName(node.getSpecializations()[0])).string(".class)").end();
+
+            for (int i = 1; i < node.getSpecializations().length; i++) {
+                SpecializationData specialization = node.getSpecializations()[i];
+                body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeClassName(specialization)).string(".class)").end();
+
+                if (specialization.isGeneric()) {
+                    body.startIf().string("allowed").end().startBlock();
+                } else {
+                    body.startIf().string("allowed");
+                    emitGuards(getContext(), body, " && ", specialization, true, true);
+                    body.end().startBlock();
+                }
+                body.startReturn().startNew(nodeClassName(specialization));
+                body.string(THIS_NODE_LOCAL_VAR_NAME);
+                body.end().end();
+                body.end(); // block
+            }
+            body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end();
+
+            return method;
+        }
+
+
+        private CodeExecutableElement createGeneratedGenericMethod(NodeData node) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), node.getGenericSpecialization().getReturnType().getActualType(), "generatedGeneric");
+            method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
+            addValueParameters(method, node.getGenericSpecialization(), true);
+
+            CodeTreeBuilder builder = method.createBuilder();
+            boolean ifStarted = false;
+            for (int i = 0; i < node.getSpecializations().length; i++) {
+                SpecializationData specialization = node.getSpecializations()[i];
+                if (specialization.isUninitialized()) {
+                    continue;
+                }
+                if (!specialization.isGeneric()) {
+                    if (!ifStarted) {
+                        builder.startIf();
+                        ifStarted = true;
+                    } else {
+                        builder.startElseIf();
+                    }
+                    emitGuards(getContext(), builder, "", specialization, false, true);
+                    builder.end().startBlock();
+                } else {
+                    builder.startElseBlock();
+                }
+
+                emitInvokeDoMethod(builder, specialization, 0);
+                builder.end();
+            }
+            return method;
+        }
+
+        private void emitInvokeDoMethod(CodeTreeBuilder builder, SpecializationData specialization, int level) {
+            if (specialization.getExceptions().length > 0) {
+                builder.startTryBlock();
+            }
+
+            builder.startReturn();
+            startCallOperationMethod(builder, specialization);
+            addValueParameterNamesWithCasts(context, builder, specialization);
+            builder.end().end(); // start call operation
+            builder.end(); // return
+
+            if (specialization.getExceptions().length > 0) {
+                for (SpecializationThrowsData exception : specialization.getExceptions()) {
+                    builder.end().startCatchBlock(exception.getJavaClass(), "ex" + level);
+                    emitInvokeDoMethod(builder, exception.getTransitionTo(), level + 1);
+                }
+                builder.end();
+            }
+        }
+    }
+
+    private class SpecializedNodeFactory extends ClassElementFactory<SpecializationData> {
+
+
+        public SpecializedNodeFactory(ProcessorContext context) {
+            super(context);
+        }
+
+        @Override
+        public CodeTypeElement create(SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeClassName(specialization), node.getNodeType(), false);
+            return clazz;
+        }
+
+        @Override
+        protected void createChildren(SpecializationData specialization) {
+            CodeTypeElement clazz = getElement();
+            NodeData node = specialization.getNode();
+
+            TypeElement superTypeElement = Utils.fromTypeMirror(clazz.getSuperclass());
+            for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) {
+                ExecutableElement superConstructor = createSuperConstructor(clazz, constructor);
+                if (superConstructor != null) {
+                    clazz.add(superConstructor);
+                }
+            }
+
+            for (ExecutableTypeData execType : node.getExecutableTypes()) {
+                if (execType.isFinal()) {
+                    continue;
+                }
+                CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod());
+                if (method.getParameters().size() == 1) {
+                    CodeVariableElement var = CodeVariableElement.clone(method.getParameters().get(0));
+                    var.setName("frame");
+                    method.getParameters().set(0, var);
+                }
+                method.getModifiers().remove(Modifier.ABSTRACT);
+                clazz.add(method);
+
+                TypeData primaryType = specialization.getReturnType().getActualTypeData(node.getTypeSystem());
+                if (primaryType == execType.getType()) {
+                    buildFunctionalExecuteMethod(method.createBuilder(), specialization);
+                } else {
+                    buildCastingExecuteMethod(method.createBuilder(), specialization, execType.getType());
+                }
+            }
+
+            if (node.needsRewrites(getContext()) && !specialization.isGeneric() && !specialization.isUninitialized()) {
+                buildSpecializeStateMethod(clazz, specialization);
+            }
+        }
+
+        private void buildCastingExecuteMethod(CodeTreeBuilder builder, SpecializationData specialization, TypeData type) {
+            NodeData node = specialization.getNode();
+            TypeSystemData typeSystem = node.getTypeSystem();
+
+            if (!type.isVoid()) {
+                builder.startStatement().type(specialization.getReturnType().getActualType()).string(" result").end();
+            }
+
+            TypeData primaryType = specialization.getReturnType().getActualTypeData(typeSystem);
+            ExecutableTypeData execType = specialization.getNode().findExecutableType(primaryType);
+
+            boolean needsTry = !specialization.getReturnType().getActualTypeData(typeSystem).isGeneric();
+            if (needsTry) {
+                builder.startTryBlock();
+            }
+
+            builder.startStatement();
+            if (!type.isVoid()) {
+                builder.string("result = ");
+            }
+            buildExecute(builder, null, execType);
+            builder.end(); // statement
+
+            if (needsTry) {
+                builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
+
+                if (!type.isVoid()) {
+                    builder.startReturn();
+                    if (!type.isGeneric()) {
+                        startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.expectTypeMethodName(type));
+                    }
+
+                    builder.string("ex.getResult()");
+
+                    if (!type.isGeneric()) {
+                        builder.end().end();
+                    }
+                    builder.end(); // return
+                } else {
+                    builder.string("// ignore").newLine();
+                }
+            }
+            builder.end(); // try/catch
+
+            if (!type.isVoid()) {
+                builder.startReturn();
+                if (!type.isGeneric()) {
+                    startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.expectTypeMethodName(type));
+                }
+                builder.string("result");
+                if (!type.isGeneric()) {
+                    builder.end().end();
+                }
+                builder.end(); // return
+            }
+        }
+
+        private void buildFunctionalExecuteMethod(CodeTreeBuilder builder, SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            TypeSystemData typeSystem = node.getTypeSystem();
+
+            for (NodeFieldData field : node.getFields()) {
+                if (field.getExecutionKind() == ExecutionKind.IGNORE) {
+                    continue;
+                }
+
+                ActualParameter parameterType = specialization.findParameter(field.getName());
+
+                if (parameterType.getActualTypeData(typeSystem).isGeneric()) {
+                    buildGenericValueExecute(builder, specialization, field, null);
+                } else {
+                    buildSpecializedValueExecute(builder, specialization, field);
+                }
+            }
+
+            if (specialization.hasDynamicGuards()) {
+                builder.startIf();
+                emitGuards(getContext(), builder, "", specialization, false, false);
+                builder.end().startBlock();
+            }
+            if (specialization.getExceptions().length > 0) {
+                builder.startTryBlock();
+            }
+
+            if (specialization.isUninitialized()) {
+                for (TemplateMethod listener : node.getSpecializationListeners()) {
+                    builder.startStatement();
+                    startCallOperationMethod(builder, listener);
+                    addValueParameterNames(builder, listener, null, false);
+                    builder.end().end();
+                    builder.end(); // statement
+                }
+
+                builder.startStatement();
+                builder.startCall("replace");
+                if (node.needsRewrites(getContext())) {
+                    builder.startCall(factoryClassName(node), "specialize");
+                    builder.string("this");
+                    builder.typeLiteral(builder.getRoot().getEnclosingClass().asType());
+                    addValueParameterNames(builder, specialization, null, false);
+                    builder.end(); // call replace, call specialize
+                } else {
+                    builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end();
+                }
+                builder.end().end();
+            }
+
+            if ((specialization.isUninitialized() || specialization.isGeneric()) && node.needsRewrites(getContext())) {
+                builder.startReturn().startCall(factoryClassName(node), "generatedGeneric");
+                builder.string("this");
+                addValueParameterNames(builder, specialization, null, true);
+                builder.end().end();
+            } else {
+                builder.startReturn();
+
+                if (specialization.isUninitialized()) {
+                    startCallOperationMethod(builder, specialization.getNode().getGenericSpecialization());
+                } else {
+                    startCallOperationMethod(builder, specialization);
+                }
+                addValueParameterNames(builder, specialization, null, false);
+                builder.end().end(); // operation call
+                builder.end(); // return
+            }
+
+            if (specialization.getExceptions().length > 0) {
+                for (SpecializationThrowsData exception : specialization.getExceptions()) {
+                    builder.end().startCatchBlock(exception.getJavaClass(), "ex");
+                    buildThrowSpecialize(builder, exception.getTransitionTo(), null);
+                }
+                builder.end();
+            }
+            if (specialization.hasDynamicGuards()) {
+                builder.end().startElseBlock();
+                buildThrowSpecialize(builder, specialization.findNextSpecialization(), null);
+                builder.end();
+            }
+        }
+
+        private void buildGenericValueExecute(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData field, NodeFieldData exceptionSpec) {
+            ActualParameter specParameter = specialization.findParameter(field.getName());
+
+            boolean shortCircuit = startShortCircuit(builder, specialization,
+                            field, exceptionSpec);
+
+            builder.startStatement();
+            if (!shortCircuit) {
+                builder.type(specialization.getNode().getTypeSystem().getGenericType());
+                builder.string(" ");
+            }
+
+            builder.string(valueName(specialization, specParameter));
+            builder.string(" = ");
+            ExecutableTypeData genericExecutableType = field.getNodeData().findGenericExecutableType(getContext());
+            if (genericExecutableType == null) {
+                throw new AssertionError("Must have generic executable type. Parser validation most likely failed. " + Arrays.toString(field.getNodeData().getExecutableTypes()));
+            }
+            buildExecute(builder, field, genericExecutableType);
+            builder.end();
+
+            endShortCircuit(builder, shortCircuit);
+        }
+
+        private void buildExecute(CodeTreeBuilder builder, NodeFieldData field, ExecutableTypeData execType) {
+            if (field != null) {
+                Element accessElement = field.getAccessElement();
+                if (accessElement.getKind() == ElementKind.METHOD) {
+                    builder.startCall(accessElement.getSimpleName().toString()).end();
+                } else if (accessElement.getKind() == ElementKind.FIELD) {
+                    builder.string("this.").string(accessElement.getSimpleName().toString());
+                } else {
+                    throw new AssertionError();
+                }
+                builder.string(".");
+            }
+            builder.startCall(execType.getMethodName());
+            if (execType.getParameters().length == 1) {
+                builder.string("frame");
+            }
+            builder.end();
+        }
+
+
+        private void buildSpecializedValueExecute(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData field) {
+            ActualParameter param = specialization.findParameter(field.getName());
+            boolean shortCircuit = startShortCircuit(builder, specialization, field, null);
+
+            if (!shortCircuit) {
+                builder.startStatement().type(param.getActualType()).string(" ").string(valueName(specialization, param)).end();
+            }
+
+            ExecutableTypeData execType = field.getNodeData().findExecutableType(param.getActualTypeData(field.getNodeData().getTypeSystem()));
+
+            if (execType.hasUnexpectedValue(getContext())) {
+                builder.startTryBlock();
+            }
+
+            builder.startStatement().string(valueName(field)).string(" = ");
+            buildExecute(builder, field, execType);
+            builder.end();
+
+
+            if (execType.hasUnexpectedValue(getContext())) {
+                builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
+                boolean execute = false;
+                for (NodeFieldData exField : specialization.getNode().getFields()) {
+                    if (exField.getExecutionKind() == ExecutionKind.IGNORE) {
+                        continue;
+                    }
+                    if (execute) {
+                        buildGenericValueExecute(builder, specialization.getNode().getGenericSpecialization(), exField, field);
+                    } else if (exField == field) {
+                        execute = true;
+                    }
+                }
+                buildThrowSpecialize(builder, specialization.findNextSpecialization(), param.getSpecification());
+                builder.end(); // catch block
+            }
+
+            endShortCircuit(builder, shortCircuit);
+            builder.newLine();
+        }
+
+
+        private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization,
+                        NodeFieldData forField, NodeFieldData exceptionField) {
+            if (forField.getExecutionKind() != ExecutionKind.SHORT_CIRCUIT) {
+                return false;
+            }
+
+            ActualParameter parameter = specialization.findParameter(forField.getName());
+            ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter);
+
+            int shortCircuitIndex = 0;
+            for (NodeFieldData field : specialization.getNode().getFields()) {
+                if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) {
+                    if (field == forField) {
+                        break;
+                    }
+                    shortCircuitIndex++;
+                }
+            }
+
+            builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(specialization, shortCircuitParam)).string(" = ");
+            ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex];
+
+            startCallOperationMethod(builder, shortCircuitData);
+            addValueParameterNames(builder, shortCircuitData, exceptionField != null ? exceptionField.getName() : null, false);
+            builder.end().end(); // call operation
+
+            builder.end(); // statement
+
+            builder.declaration(parameter.getActualType(), valueName(specialization, parameter),
+                            CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType()));
+            builder.startIf().string(shortCircuitParam.getSpecification().getName()).end();
+            builder.startBlock();
+
+            return true;
+        }
+
+
+        private void endShortCircuit(CodeTreeBuilder builder, boolean shortCircuit) {
+            if (shortCircuit) {
+                builder.end();
+            }
+        }
+
+        private void buildThrowSpecialize(CodeTreeBuilder builder, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) {
+            boolean canThrowUnexpected = Utils.canThrowType(builder.findMethod().getThrownTypes(), getContext().getTruffleTypes().getUnexpectedValueException());
+
+            CodeTreeBuilder specializeCall = CodeTreeBuilder.createBuilder();
+            specializeCall.startCall("specialize");
+            specializeCall.string(nodeClassName(nextSpecialization) + ".class");
+            addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionSpec != null ? exceptionSpec.getName() : null, true);
+            specializeCall.end().end();
+
+            if (canThrowUnexpected) {
+                builder.startThrow();
+                builder.startNew(getContext().getTruffleTypes().getUnexpectedValueException());
+                builder.tree(specializeCall.getRoot());
+                builder.end().end();
+            } else {
+                builder.startReturn();
+                builder.tree(specializeCall.getRoot());
+                builder.end();
+            }
+
+        }
+
+        private void buildSpecializeStateMethod(CodeTypeElement clazz, SpecializationData specialization) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), specialization.getNode().getTypeSystem().getGenericType(), "specialize");
+            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState"));
+            addValueParameters(method, specialization.getNode().getGenericSpecialization(), true);
+            clazz.add(method);
+
+            CodeTreeBuilder builder = method.createBuilder();
+            for (TemplateMethod listener : specialization.getNode().getSpecializationListeners()) {
+                builder.startStatement();
+                startCallOperationMethod(builder, listener);
+                addValueParameterNames(builder, listener, null, false);
+                builder.end().end(); // call operation
+                builder.end(); // statement
+            }
+
+            builder.startStatement();
+            builder.startCall("replace");
+            builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState");
+            addValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, false);
+            builder.end();
+            builder.end(); // call replace
+            builder.end(); // statement
+
+            ExecutableElement generatedGeneric = clazz.getEnclosingClass().getMethod("generatedGeneric");
+
+            CodeTreeBuilder genericBuilder = CodeTreeBuilder.createBuilder();
+            genericBuilder.startCall(factoryClassName(specialization.getNode()), "generatedGeneric");
+            genericBuilder.string("this");
+            addValueParameterNames(genericBuilder, specialization.getNode().getGenericSpecialization(), null, true);
+            genericBuilder.end(); // call generated generic
+
+            if (Utils.isVoid(generatedGeneric.getReturnType())) {
+                builder.declaration(generatedGeneric.getReturnType(), "genericResult", genericBuilder.getRoot());
+                builder.startReturn().string("null").end();
+            } else {
+                builder.startReturn().tree(genericBuilder.getRoot()).end();
+            }
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,332 @@
+/*
+ * 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.codegen.processor.node;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind;
+import com.oracle.truffle.codegen.processor.node.NodeFieldData.FieldKind;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.typesystem.*;
+
+
+public class NodeData extends Template {
+
+    private NodeData parent;
+    private List<NodeData> declaredChildren;
+
+    private final TypeSystemData typeSystem;
+
+    private NodeFieldData[] fields;
+    private SpecializationData[] specializations;
+    private TemplateMethod[] specializationListeners;
+    private GuardData[] guards;
+    private ExecutableTypeData[] executableTypes;
+
+    private TypeMirror nodeType;
+
+    public NodeData(TypeElement type, TypeSystemData typeSystem) {
+        super(type, null);
+        this.typeSystem = typeSystem;
+    }
+
+    public TypeMirror getNodeType() {
+        if (nodeType != null) {
+            return nodeType;
+        }
+        return getTemplateType().asType();
+    }
+
+    public boolean needsFactory() {
+        if (specializations == null) {
+            return false;
+        }
+        boolean noSpecialization = true;
+        for (SpecializationData specialization : specializations) {
+            noSpecialization = noSpecialization && specialization.isGeneric() || specialization.isUninitialized();
+        }
+        return !noSpecialization;
+    }
+
+    void setDeclaredChildren(List<NodeData> declaredChildren) {
+        this.declaredChildren = declaredChildren;
+
+        for (NodeData child : declaredChildren) {
+            child.parent = this;
+        }
+    }
+
+    public NodeData getParent() {
+        return parent;
+    }
+
+    public List<NodeData> getDeclaredChildren() {
+        return declaredChildren;
+    }
+
+    public void setNodeType(TypeMirror nodeType) {
+        this.nodeType = nodeType;
+    }
+
+    public List<TemplateMethod> getAllTemplateMethods() {
+        List<TemplateMethod> methods = new ArrayList<>();
+
+        for (SpecializationData specialization : getSpecializations()) {
+            methods.add(specialization);
+            if (specialization.getShortCircuits() != null) {
+                methods.addAll(Arrays.asList(specialization.getShortCircuits()));
+            }
+        }
+
+        methods.addAll(Arrays.asList(getSpecializationListeners()));
+        methods.addAll(Arrays.asList(getExecutableTypes()));
+        methods.addAll(Arrays.asList(getGuards()));
+
+        return methods;
+    }
+
+
+    public TemplateMethod[] getSpecializationListeners() {
+        return specializationListeners;
+    }
+
+    public List<GuardData> findGuards(String name) {
+        List<GuardData> foundGuards = new ArrayList<>();
+        for (GuardData guardData : getGuards()) {
+            if (guardData.getMethodName().equals(name)) {
+                foundGuards.add(guardData);
+            }
+        }
+        return foundGuards;
+    }
+
+    public ExecutableTypeData[] getExecutableTypes() {
+        return executableTypes;
+    }
+
+    public ExecutableTypeData findGenericExecutableType(ProcessorContext context) {
+        List<ExecutableTypeData> types = findGenericExecutableTypes(context);
+        if (types.size() == 1) {
+            return types.get(0);
+        } else {
+            ExecutableTypeData execType = null;
+            for (ExecutableTypeData type : types) {
+                if (!type.getReturnType().getActualTypeData(getTypeSystem()).isVoid()) {
+                    if (execType != null) {
+                        // multiple generic types not allowed
+                        return null;
+                    }
+                    execType = type;
+                }
+            }
+            return execType;
+        }
+    }
+
+    private List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context) {
+        List<ExecutableTypeData> types = new ArrayList<>();
+        for (ExecutableTypeData type : executableTypes) {
+            if (!type.hasUnexpectedValue(context)) {
+                types.add(type);
+            }
+        }
+        return types;
+    }
+
+    public ExecutableTypeData findExecutableType(TypeData prmitiveType) {
+        for (ExecutableTypeData type : executableTypes) {
+            if (Utils.typeEquals(type.getType().getPrimitiveType(), prmitiveType.getPrimitiveType())) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    public SpecializationData findUniqueSpecialization(TypeData type) {
+        SpecializationData result = null;
+        for (SpecializationData specialization : specializations) {
+            if (specialization.getReturnType().getActualTypeData(getTypeSystem()) == type) {
+                if (result != null) {
+                    // Result not unique;
+                    return null;
+                }
+                result = specialization;
+            }
+        }
+        return result;
+    }
+
+    public TypeMirror[] getExecutablePrimitiveTypeMirrors() {
+        TypeMirror[] typeMirrors = new TypeMirror[executableTypes.length];
+        for (int i = 0; i < executableTypes.length; i++) {
+            typeMirrors[i] = executableTypes[i].getType().getPrimitiveType();
+        }
+        return typeMirrors;
+    }
+
+    void setExecutableTypes(ExecutableTypeData[] declaredExecuableTypes) {
+        this.executableTypes = declaredExecuableTypes;
+    }
+
+    void setFields(NodeFieldData[] fields) {
+        this.fields = fields;
+    }
+
+    void setSpecializations(SpecializationData[] specializations) {
+        this.specializations = specializations;
+    }
+
+    void setSpecializationListeners(TemplateMethod[] specializationListeners) {
+        this.specializationListeners = specializationListeners;
+    }
+
+    void setGuards(GuardData[] guards) {
+        this.guards = guards;
+    }
+
+    public GuardData[] getGuards() {
+        return guards;
+    }
+
+    public NodeFieldData[] filterFields(FieldKind fieldKind, ExecutionKind usage) {
+        List<NodeFieldData> filteredFields = new ArrayList<>();
+        NodeFieldData[] resolvedFields = getFields();
+        if (fields != null) {
+            for (NodeFieldData field : resolvedFields) {
+                if (usage == null || field.getExecutionKind() == usage) {
+                    if (fieldKind == null || field.getKind() == fieldKind) {
+                        filteredFields.add(field);
+                    }
+                }
+            }
+        }
+        return filteredFields.toArray(new NodeFieldData[filteredFields.size()]);
+    }
+
+    public boolean hasUnexpectedExecutableTypes(ProcessorContext context) {
+        for (ExecutableTypeData type : getExecutableTypes()) {
+            if (type.hasUnexpectedValue(context)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean needsRewrites(ProcessorContext context) {
+        boolean needsRewrites = false;
+        for (NodeFieldData field : getFields()) {
+            if (field.getExecutionKind() == ExecutionKind.DEFAULT
+                            || field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) {
+                if (!field.getNodeData().hasUnexpectedExecutableTypes(context)) {
+                    continue;
+                }
+
+                needsRewrites = true;
+                break;
+            }
+        }
+
+        needsRewrites &= specializations.length >= 2;
+        return needsRewrites;
+    }
+
+    public SpecializationData getGenericSpecialization() {
+        for (SpecializationData specialization : specializations) {
+            if (specialization.isGeneric()) {
+                return specialization;
+            }
+        }
+        return null;
+    }
+
+    public TypeSystemData getTypeSystem() {
+        if (typeSystem != null) {
+            return typeSystem;
+        } else {
+            return null;
+        }
+    }
+
+    public NodeFieldData[] getFields() {
+        return fields;
+    }
+
+    public NodeFieldData[] getDeclaredFields() {
+        return fields;
+    }
+
+    public SpecializationData[] getSpecializations() {
+        return specializations;
+    }
+
+    public String dump() {
+        StringBuilder b = new StringBuilder();
+        b.append(String.format("[name = %s\n" +
+                        "  typeSystem = %s\n" +
+                        "  fields = %s\n" +
+                        "  types = %s\n" +
+                        "  specializations = %s\n" +
+                        "  guards = %s\n" +
+                        "]", Utils.getQualifiedName(getTemplateType()),
+                            getTypeSystem(),
+                            dumpList(fields),
+                            dumpList(getExecutableTypes()),
+                            dumpList(getSpecializations()),
+                            dumpList(guards)
+                        ));
+        return b.toString();
+    }
+
+    private static String dumpList(Object[] array) {
+        if (array == null) {
+            return "null";
+        }
+
+        StringBuilder b = new StringBuilder();
+        b.append("[");
+        for (Object object : array) {
+            b.append("\n");
+            b.append("    ");
+            b.append(object);
+            b.append(", ");
+        }
+        b.append("\n  ]");
+        return b.toString();
+    }
+
+    public NodeFieldData findField(String name) {
+        for (NodeFieldData field : getFields()) {
+            if (field.getName().equals(name)) {
+                return field;
+            }
+        }
+        return null;
+    }
+
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,95 @@
+/*
+ * 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.codegen.processor.node;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+
+public class NodeFieldData {
+
+    public enum FieldKind {
+        FIELD, CHILD, CHILDREN
+    }
+
+    public enum ExecutionKind {
+        DEFAULT, IGNORE, SHORT_CIRCUIT
+    }
+
+    private final VariableElement fieldElement;
+    private final Element accessElement;
+    private final AnnotationMirror childAnnotationMirror;
+
+    private final FieldKind fieldKind;
+    private final ExecutionKind executionKind;
+    private final NodeData nodeData;
+
+    public NodeFieldData(NodeData typeNodeData, VariableElement fieldElement, Element accessElement, AnnotationMirror childAnnotationMirror,
+                    FieldKind fieldKind, ExecutionKind executionKind) {
+        this.fieldElement = fieldElement;
+        this.accessElement = accessElement;
+        this.childAnnotationMirror = childAnnotationMirror;
+        this.nodeData = typeNodeData;
+        this.fieldKind = fieldKind;
+        this.executionKind = executionKind;
+    }
+
+    public VariableElement getFieldElement() {
+        return fieldElement;
+    }
+
+    public Element getAccessElement() {
+        return accessElement;
+    }
+
+    public AnnotationMirror getChildAnnotationMirror() {
+        return childAnnotationMirror;
+    }
+
+    public TypeMirror getType() {
+        return fieldElement.asType();
+    }
+
+    public FieldKind getKind() {
+        return fieldKind;
+    }
+
+    public ExecutionKind getExecutionKind() {
+        return executionKind;
+    }
+
+    public NodeData getNodeData() {
+        return nodeData;
+    }
+
+    public String getName() {
+        return fieldElement.getSimpleName().toString();
+    }
+
+
+    @Override
+    public String toString() {
+        return "NodeFieldData[name=" + getName() + ", kind=" + fieldKind + ", execution=" + executionKind + "]";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,785 @@
+/*
+ * 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.codegen.processor.node;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.api.nodes.Node.Child;
+import com.oracle.truffle.api.nodes.Node.Children;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.ast.*;
+import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind;
+import com.oracle.truffle.codegen.processor.node.NodeFieldData.FieldKind;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.typesystem.*;
+
+public class NodeParser extends TemplateParser<NodeData>{
+
+    private static final List<Class<? extends Annotation>> annotations = Arrays.asList(
+                    Generic.class, GuardCheck.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class,
+                    SpecializationGuard.class, SpecializationListener.class, SpecializationThrows.class);
+
+    private static final boolean DEBUG = false;
+
+    private Map<String, NodeData> parsedNodes;
+    private TypeElement originalType;
+
+    public NodeParser(ProcessorContext c) {
+        super(c);
+    }
+
+    @Override
+    protected NodeData parse(Element element, AnnotationMirror mirror) {
+        assert element instanceof TypeElement;
+        try {
+            parsedNodes = new HashMap<>();
+            originalType = (TypeElement) element;
+
+            return parseInnerClassHierarchy((TypeElement) element);
+        } finally {
+            if (DEBUG) {
+                NodeData parsed = parsedNodes.get(Utils.getQualifiedName(originalType));
+                if (parsed != null) {
+                    String dump = parsed.dump();
+                    log.error("Node parsed: %s", dump);
+                    System.out.println("Parsed: " + dump);
+                }
+            }
+            parsedNodes = null;
+            originalType = null;
+        }
+    }
+
+    @Override
+    public boolean isDelegateToRootDeclaredType() {
+        return true;
+    }
+
+    private NodeData parseInnerClassHierarchy(TypeElement rootType) {
+        List<? extends TypeElement> types = ElementFilter.typesIn(rootType.getEnclosedElements());
+        List<NodeData> children = new ArrayList<>();
+        for (TypeElement childElement : types) {
+            NodeData childNode = parseInnerClassHierarchy(childElement);
+            if (childNode != null) {
+                children.add(childNode);
+            }
+        }
+        NodeData rootNode = resolveNode(rootType);
+        if (rootNode == null && children.size() > 0) {
+            rootNode = new NodeData(rootType, null);
+        }
+        if (rootNode != null) {
+            rootNode.setDeclaredChildren(children);
+        }
+        return rootNode;
+    }
+
+    private NodeData resolveNode(TypeElement currentType) {
+        String typeName = Utils.getQualifiedName(currentType);
+        if (!parsedNodes.containsKey(typeName)) {
+            NodeData node = parseNode(currentType);
+            if (node != null) {
+                parsedNodes.put(typeName, node);
+            }
+            return node;
+        }
+        return parsedNodes.get(typeName);
+    }
+
+    private NodeData parseNode(TypeElement type) {
+        if (Utils.findAnnotationMirror(processingEnv, type, GeneratedBy.class) != null) {
+            // generated nodes get called again.
+            return null;
+        }
+        if (!Utils.isAssignable(type.asType(), context.getTruffleTypes().getNode())) {
+            return null; // not a node
+        }
+
+        List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(type));
+        List<TypeElement> typeHierarchy = findSuperClasses(new ArrayList<TypeElement>(), type);
+        Collections.reverse(typeHierarchy);
+
+        AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class);
+        if (typeSystemMirror == null) {
+            log.error(originalType, "No @%s annotation found in type hierarchy.", TypeSystemReference.class.getSimpleName());
+            return null;
+        }
+
+        TypeMirror typeSytemType = Utils.getAnnotationValueType(typeSystemMirror, "value");
+        final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true);
+        if (typeSystem == null) {
+            log.error(originalType, "The used type system '%s' is invalid.", Utils.getQualifiedName(typeSytemType));
+            return null;
+        }
+
+        NodeData nodeData = new NodeData(type, typeSystem);
+
+        nodeData.setExtensionElements(getExtensionParser().parseAll(type, elements));
+        if (nodeData.getExtensionElements() != null) {
+            elements.addAll(nodeData.getExtensionElements());
+        }
+
+        List<ExecutableTypeData> executableTypes = filterExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements));
+
+        nodeData.setExecutableTypes(executableTypes.toArray(new ExecutableTypeData[executableTypes.size()]));
+
+        parsedNodes.put(Utils.getQualifiedName(type), nodeData); // node fields will resolve node types, to avoid endless loops
+
+        NodeFieldData[] fields = parseFields(nodeData, elements, typeHierarchy);
+        if (fields == null) {
+            return null;
+        }
+        nodeData.setFields(fields);
+
+
+        List<SpecializationData> genericSpecializations = new GenericParser(context, nodeData).parse(elements);
+        List<GuardData> guards = new GuardParser(context, nodeData, nodeData.getTypeSystem()).parse(elements);
+        nodeData.setGuards(guards.toArray(new GuardData[guards.size()]));
+
+        SpecializationMethodParser specializationParser = new SpecializationMethodParser(context, nodeData);
+        List<SpecializationData> specializations = specializationParser.parse(elements);
+        List<ShortCircuitData> shortCircuits = new ShortCircuitParser(context, nodeData).parse(elements);
+        List<TemplateMethod> listeners = new SpecializationListenerParser(context, nodeData).parse(elements);
+
+        if (specializations == null || genericSpecializations == null || shortCircuits == null  || listeners == null || guards == null) {
+            return null;
+        }
+
+        SpecializationData genericSpecialization = null;
+        if (genericSpecializations.size() > 1) {
+            for (SpecializationData generic : genericSpecializations) {
+                log.error(generic.getMethod(), "Only one method with @%s is allowed per operation.", Generic.class.getSimpleName());
+            }
+            return null;
+        } else if (genericSpecializations.size() == 1) {
+            genericSpecialization = genericSpecializations.get(0);
+        }
+
+        if (specializations.size() > 1 && genericSpecialization == null) {
+            log.error(originalType, "Need a @%s method.", Generic.class.getSimpleName());
+            return null;
+        }
+
+        Collections.sort(specializations, new Comparator<SpecializationData>() {
+            @Override
+            public int compare(SpecializationData o1, SpecializationData o2) {
+                return compareSpecialization(typeSystem, o1, o2);
+            }
+        });
+
+        List<SpecializationData> allSpecializations = new ArrayList<>(specializations);
+        if (genericSpecialization != null) {
+            allSpecializations.add(genericSpecialization);
+            CodeExecutableElement uninitializedMethod = new CodeExecutableElement(Utils.modifiers(Modifier.PUBLIC), context.getType(void.class), "doUninitialized");
+            TemplateMethod uninializedMethod = new TemplateMethod(nodeData, genericSpecialization.getSpecification(), uninitializedMethod,
+                            genericSpecialization.getMarkerAnnotation(), genericSpecialization.getReturnType(), genericSpecialization.getParameters());
+            allSpecializations.add(0, new SpecializationData(uninializedMethod, false, true));
+        }
+
+        for (SpecializationData specialization : allSpecializations) {
+            specialization.setNode(nodeData);
+        }
+
+        // verify order is not ambiguous
+        if (!verifySpecializationOrder(typeSystem, specializations)) {
+            return null;
+        }
+
+        nodeData.setSpecializations(allSpecializations.toArray(new SpecializationData[allSpecializations.size()]));
+        nodeData.setSpecializationListeners(listeners.toArray(new TemplateMethod[listeners.size()]));
+
+        if (!verifyMissingAbstractMethods(nodeData, elements)) {
+            return null;
+        }
+
+        if (!assignShortCircuitsToSpecializations(nodeData, allSpecializations, shortCircuits)) {
+            return null;
+        }
+
+        if (!verifyConstructors(nodeData)) {
+            return null;
+        }
+
+        if (!verifyNamingConvention(specializations, "do")) {
+            return null;
+        }
+
+        if (!verifyNamesUnique(specializations)) {
+            return null;
+        }
+
+        if (!verifyNamingConvention(shortCircuits, "needs")) {
+            return null;
+        }
+
+        if (!verifySpecializationThrows(typeSystem, specializations)) {
+            return null;
+        }
+
+        return nodeData;
+    }
+
+    private boolean verifyMissingAbstractMethods(NodeData nodeData, List<Element> elements) {
+        if (nodeData.needsFactory()) {
+            // missing abstract methods only needs to be implemented
+            // if we need go generate factory for it.
+            return true;
+        }
+
+        Set<Element> unusedElements = new HashSet<>(elements);
+        for (TemplateMethod method : nodeData.getAllTemplateMethods()) {
+            unusedElements.remove(method.getMethod());
+        }
+        if (nodeData.getExtensionElements() != null) {
+            unusedElements.removeAll(nodeData.getExtensionElements());
+        }
+
+        boolean valid = true;
+        for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) {
+            if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) {
+                context.getLog().error(nodeData.getTemplateType(), "The type %s must implement the inherited abstract method %s.", Utils.getSimpleName(nodeData.getTemplateType()), Utils.getReadableSignature(unusedMethod));
+                valid = false;
+            }
+        }
+
+        return valid;
+    }
+
+    private boolean verifyConstructors(NodeData nodeData) {
+        TypeElement type = Utils.fromTypeMirror(nodeData.getNodeType());
+        if (!nodeData.needsRewrites(context)) {
+            // no specialization constructor is needed if the node never rewrites.
+            return true;
+        }
+
+        List<ExecutableElement> constructors = ElementFilter.constructorsIn(type.getEnclosedElements());
+        for (ExecutableElement e : constructors) {
+            if (e.getParameters().size() == 1) {
+                TypeMirror firstArg = e.getParameters().get(0).asType();
+                if (Utils.typeEquals(firstArg, nodeData.getNodeType())) {
+                    if (e.getModifiers().contains(Modifier.PRIVATE)) {
+                        context.getLog().error(e, "The specialization constructor must not be private.");
+                        return false;
+                    } else if (constructors.size() <= 1) {
+                        context.getLog().error(e, "The specialization constructor must not be the only constructor. The definition of an alternative constructor is required.");
+                        return false;
+                    }
+                    return true;
+                }
+            }
+        }
+
+        // not found
+        context.getLog().error(type, "Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type));
+        return false;
+    }
+
+    private static List<ExecutableTypeData> filterExecutableTypes(List<ExecutableTypeData> executableTypes) {
+        List<ExecutableTypeData> filteredExecutableTypes = new ArrayList<>();
+        for (ExecutableTypeData t1 : executableTypes) {
+            boolean add = true;
+            for (ExecutableTypeData t2 : executableTypes) {
+                if (t1 == t2) {
+                    continue;
+                }
+                if (Utils.typeEquals(t1.getType().getPrimitiveType(), t2.getType().getPrimitiveType())) {
+                    if (t1.isFinal() && !t2.isFinal()) {
+                        add = false;
+                    }
+                }
+            }
+            if (add) {
+                filteredExecutableTypes.add(t1);
+            }
+        }
+        return filteredExecutableTypes;
+    }
+
+    private AnnotationMirror findFirstAnnotation(List<? extends Element> elements, Class<? extends Annotation> annotation) {
+        for (Element element : elements) {
+            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, element, annotation);
+            if (mirror != null) {
+                return mirror;
+            }
+        }
+        return null;
+    }
+
+    private NodeFieldData[] parseFields(NodeData nodeData, List<? extends Element> elements, final List<TypeElement> typeHierarchy) {
+        AnnotationMirror executionOrderMirror = findFirstAnnotation(typeHierarchy, ExecuteChildren.class);
+        List<String> executionDefinition = null;
+        if (executionOrderMirror != null) {
+            executionDefinition = new ArrayList<>();
+            for (Object object : Utils.getAnnotationValueList(executionOrderMirror, "value")) {
+                executionDefinition.add((String) object);
+            }
+        }
+
+        Set<String> shortCircuits = new HashSet<>();
+        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
+            if (mirror != null) {
+                shortCircuits.add(Utils.getAnnotationValueString(mirror, "value"));
+            }
+        }
+
+        boolean valid = true;
+
+        List<NodeFieldData> fields = new ArrayList<>();
+        for (VariableElement var : ElementFilter.fieldsIn(elements)) {
+            if (var.getModifiers().contains(Modifier.STATIC)) {
+                continue;
+            }
+
+            if (executionDefinition != null) {
+                if (!executionDefinition.contains(var.getSimpleName().toString())) {
+                    continue;
+                }
+            }
+
+            NodeFieldData field = parseField(nodeData, var, shortCircuits);
+            if (field != null) {
+                if (field.getExecutionKind() != ExecutionKind.IGNORE) {
+                    fields.add(field);
+                }
+            } else {
+                valid = false;
+            }
+        }
+
+        //TODO parse getters
+        if (!valid) {
+            return null;
+        }
+
+        NodeFieldData[] fieldArray =  fields.toArray(new NodeFieldData[fields.size()]);
+        sortByExecutionOrder(fieldArray, executionDefinition == null ? Collections.<String>emptyList() : executionDefinition, typeHierarchy);
+        return fieldArray;
+    }
+
+    private NodeFieldData parseField(NodeData parentNodeData, VariableElement var, Set<String> foundShortCircuits) {
+        AnnotationMirror childMirror = Utils.findAnnotationMirror(processingEnv, var, Child.class);
+        AnnotationMirror childrenMirror = Utils.findAnnotationMirror(processingEnv, var, Children.class);
+
+        FieldKind kind;
+
+        ExecutionKind execution;
+        if (foundShortCircuits.contains(var.getSimpleName().toString())) {
+            execution = ExecutionKind.SHORT_CIRCUIT;
+        } else {
+            execution = ExecutionKind.DEFAULT;
+        }
+
+        AnnotationMirror mirror;
+        TypeMirror nodeType;
+
+        if (childMirror != null) {
+            mirror = childMirror;
+            nodeType = var.asType();
+            kind = FieldKind.CHILD;
+        } else if (childrenMirror != null) {
+            mirror = childrenMirror;
+            nodeType = getComponentType(var.asType());
+            kind = FieldKind.CHILDREN;
+        } else {
+            mirror = null;
+            nodeType = null;
+            kind = FieldKind.FIELD;
+            execution = ExecutionKind.IGNORE;
+        }
+
+        NodeData fieldNodeData = null;
+        if (nodeType != null) {
+            fieldNodeData = resolveNode(Utils.fromTypeMirror(nodeType));
+            Element errorElement = Utils.typeEquals(parentNodeData.getTemplateType().asType(), var.getEnclosingElement().asType()) ? var : parentNodeData.getTemplateType();
+
+            if (fieldNodeData == null) {
+                //TODO redirect errors from resolve.
+                context.getLog().error(errorElement, "Node type '%s' is invalid.", Utils.getQualifiedName(nodeType));
+                return null;
+            } else if (fieldNodeData.findGenericExecutableType(context) == null) {
+                context.getLog().error(errorElement, "No executable generic type found for node '%s'.", Utils.getQualifiedName(nodeType));
+                return null;
+            }
+        }
+
+        //TODO correct handling of access elements
+        if (var.getModifiers().contains(Modifier.PRIVATE) && Utils.typeEquals(var.getEnclosingElement().asType(), parentNodeData.getTemplateType().asType())) {
+            execution = ExecutionKind.IGNORE;
+        }
+
+        return new NodeFieldData(fieldNodeData, var, findAccessElement(var), mirror, kind, execution);
+    }
+
+    private Element findAccessElement(VariableElement variableElement) {
+        Element enclosed = variableElement.getEnclosingElement();
+        if (!enclosed.getKind().isClass()) {
+            throw new IllegalArgumentException("Field must be enclosed in a class.");
+        }
+
+        String methodName;
+        if (Utils.typeEquals(variableElement.asType(), context.getType(boolean.class))) {
+            methodName = "is" + Utils.firstLetterUpperCase(variableElement.getSimpleName().toString());
+        } else {
+            methodName = "get" + Utils.firstLetterUpperCase(variableElement.getSimpleName().toString());
+        }
+
+        ExecutableElement getter = null;
+        for (ExecutableElement method : ElementFilter.methodsIn(enclosed.getEnclosedElements())) {
+            if (method.getSimpleName().toString().equals(methodName)
+                            && method.getParameters().size() == 0
+                            && !Utils.typeEquals(method.getReturnType(), context.getType(void.class))) {
+                getter = method;
+                break;
+            }
+        }
+
+        if (getter != null) {
+            return getter;
+        } else {
+            return variableElement;
+        }
+    }
+
+    private static void sortByExecutionOrder(NodeFieldData[] fields, final List<String> executionOrder, final List<TypeElement> typeHierarchy) {
+        Arrays.sort(fields, new Comparator<NodeFieldData>() {
+            @Override
+            public int compare(NodeFieldData o1, NodeFieldData o2) {
+                // sort by execution order
+                int index1 = executionOrder.indexOf(o1.getName());
+                int index2 = executionOrder.indexOf(o2.getName());
+                if (index1 == -1 || index2 == -1) {
+                    // sort by type hierarchy
+                    index1 = typeHierarchy.indexOf(o1.getFieldElement().getEnclosingElement());
+                    index2 = typeHierarchy.indexOf(o2.getFieldElement().getEnclosingElement());
+
+                    // finally sort by name (will emit warning)
+                    if (index1 == -1 || index2 == -1) {
+                        return o1.getName().compareTo(o2.getName());
+                    }
+                }
+                return index1 - index2;
+            }
+        });
+    }
+
+    private boolean assignShortCircuitsToSpecializations(NodeData nodeData,
+                    List<SpecializationData> specializations,
+                    List<ShortCircuitData> shortCircuits) {
+
+        Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(shortCircuits);
+
+        boolean valid = true;
+
+        for (NodeFieldData field : nodeData.filterFields(null, ExecutionKind.SHORT_CIRCUIT)) {
+            String valueName = field.getName();
+            List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
+
+            if (availableCircuits == null || availableCircuits.isEmpty()) {
+                log.error(nodeData.getTemplateType(),
+                                "@%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) {
+                    log.error(circuit.getMethod(), circuit.getMarkerAnnotation(), "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(nodeData, circuit)) {
+                    genericCircuit = circuit;
+                    break;
+                }
+            }
+
+            if (genericCircuit == null) {
+                log.error(nodeData.getTemplateType(),
+                                "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 valid;
+        }
+
+        NodeFieldData[] fields = nodeData.filterFields(null, ExecutionKind.SHORT_CIRCUIT);
+        for (SpecializationData specialization : specializations) {
+            ShortCircuitData[] assignedShortCuts = new ShortCircuitData[fields.length];
+
+            for (int i = 0; i < fields.length; i++) {
+                List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(fields[i].getName());
+
+                ShortCircuitData genericShortCircuit = null;
+                for (ShortCircuitData circuit : availableShortCuts) {
+                    if (circuit.isGeneric()) {
+                        genericShortCircuit = circuit;
+                    } else if (circuit.isCompatibleTo(specialization)) {
+                        assignedShortCuts[i] = circuit;
+                    }
+                }
+
+                if (assignedShortCuts[i] == null) {
+                    assignedShortCuts[i] = genericShortCircuit;
+                }
+            }
+            specialization.setShortCircuits(assignedShortCuts);
+        }
+        return true;
+    }
+
+    private boolean verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) {
+        boolean valid = true;
+        for (int i = 0; i < methods.size(); i++) {
+            TemplateMethod m1 = methods.get(i);
+            if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
+                log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Naming convention: method name must start with '%s'.", prefix);
+                valid = false;
+            }
+        }
+        return valid;
+    }
+
+    private boolean verifyNamesUnique(List<? extends TemplateMethod> methods) {
+        boolean valid = true;
+        for (int i = 0; i < methods.size(); i++) {
+            TemplateMethod m1 = methods.get(i);
+            for (int j = i + 1; j < methods.size(); j++) {
+                TemplateMethod m2 = methods.get(j);
+
+                if (m1.getMethodName().equalsIgnoreCase(m2.getMethodName())) {
+                    log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Method name '%s' used multiple times", m1.getMethodName());
+                    log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Method name '%s' used multiple times", m1.getMethodName());
+                    return false;
+                }
+            }
+        }
+        return valid;
+    }
+
+
+    private static boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) {
+        for (NodeFieldData field : node.getFields()) {
+            ActualParameter parameter = method.findParameter(field.getName());
+            if (parameter == null) {
+                continue;
+            }
+            if (!Utils.typeEquals(node.getTypeSystem().getGenericType(), parameter.getActualType())) {
+                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 TypeMirror getComponentType(TypeMirror type) {
+        if (type instanceof ArrayType) {
+            return getComponentType(((ArrayType) type).getComponentType());
+        }
+        return type;
+    }
+
+    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;
+    }
+
+
+    private boolean verifySpecializationOrder(TypeSystemData typeSystem, List<SpecializationData> specializations) {
+        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 = compareSpecializationWithoutOrder(typeSystem, m1, m2);
+
+                if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
+                    int specOrder = m1.getOrder() - m2.getOrder();
+                    if (specOrder == 0) {
+                        log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Order value %d used multiple times", m1.getOrder());
+                        log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Order value %d used multiple times", m1.getOrder());
+                        return false;
+                    } else if ((specOrder < 0 && inferredOrder > 0) || (specOrder > 0 && inferredOrder < 0)) {
+                        log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
+                        log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
+                        return false;
+                    }
+                } else if (inferredOrder == 0) {
+                    SpecializationData m = (m1.getOrder() == Specialization.DEFAULT_ORDER ? m1 : m2);
+                    log.error(m.getMethod(), m.getMarkerAnnotation(), "Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this.");
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+
+    private boolean verifySpecializationThrows(TypeSystemData typeSystem, List<SpecializationData> specializations) {
+        Map<String, SpecializationData> specializationMap = new HashMap<>();
+        for (SpecializationData spec : specializations) {
+            specializationMap.put(spec.getMethodName(), spec);
+        }
+        boolean valid = true;
+        for (SpecializationData sourceSpecialization : specializations) {
+            if (sourceSpecialization.getExceptions() != null) {
+                for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) {
+                    SpecializationData targetSpecialization = specializationMap.get(throwsData.getTransitionToName());
+                    AnnotationValue value = Utils.getAnnotationValue(throwsData.getAnnotationMirror(), "transitionTo");
+
+                    if (targetSpecialization != null)  {
+                        log.error("Specialization throws current %s target %s compare %s.", sourceSpecialization.getMethodName(), targetSpecialization.getMethodName(), compareSpecialization(typeSystem, sourceSpecialization, targetSpecialization));
+                    }
+
+                    if (targetSpecialization == null) {
+                        log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), value,
+                                        "Specialization with name '%s' not found.", throwsData.getTransitionToName());
+                        valid = false;
+                    } else if (compareSpecialization(typeSystem, sourceSpecialization, targetSpecialization) >= 0) {
+                        log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), value,
+                                        "The order of the target specializalization must be higher than the source specialization.", throwsData.getTransitionToName());
+                        valid = false;
+                    }
+
+                    for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) {
+                        if (otherThrowsData != throwsData
+                                        && Utils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) {
+                            AnnotationValue javaClassValue = Utils.getAnnotationValue(throwsData.getAnnotationMirror(), "javaClass");
+                            log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), javaClassValue,
+                                            "Duplicate exception type.", throwsData.getTransitionToName());
+                            valid = false;
+                        }
+                    }
+                }
+            }
+        }
+        return valid;
+    }
+
+
+    private static int compareSpecialization(TypeSystemData typeSystem, SpecializationData m1, SpecializationData m2) {
+        if (m1 == m2) {
+            return 0;
+        }
+        int result = compareSpecializationWithoutOrder(typeSystem, m1, m2);
+        if (result == 0) {
+            if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
+                return m1.getOrder() - m2.getOrder();
+            }
+        }
+        return result;
+    }
+
+    private static int compareSpecializationWithoutOrder(TypeSystemData typeSystem, SpecializationData m1, SpecializationData m2) {
+        if (m1.getSpecification() != m2.getSpecification()) {
+            throw new UnsupportedOperationException("Cannot compare two specializations with different specifications.");
+        }
+
+        int result = compareActualParameter(typeSystem, m1.getReturnType(), m2.getReturnType());
+
+        for (ParameterSpec spec : m1.getSpecification().getParameters()) {
+            ActualParameter p1 = m1.findParameter(spec);
+            ActualParameter p2 = m2.findParameter(spec);
+
+            if (p1 != null && p2 != null && !Utils.typeEquals(p1.getActualType(), p2.getActualType())) {
+                int typeResult = compareActualParameter(typeSystem, p1, p2);
+                if (result == 0) {
+                    result = typeResult;
+                } else if (Math.signum(result) != Math.signum(typeResult)) {
+                    // We cannot define an order.
+                    return 0;
+                }
+            }
+        }
+        return result;
+    }
+
+    private static int compareActualParameter(TypeSystemData typeSystem, ActualParameter p1, ActualParameter p2) {
+        int index1 = typeSystem.findType(p1.getActualType());
+        int index2 = typeSystem.findType(p2.getActualType());
+
+        assert index1 != index2;
+        assert !(index1 == -1 ^ index2 == -1);
+
+        return index1 - index2;
+    }
+
+
+    @Override
+    public Class< ? extends Annotation> getAnnotationType() {
+        return null;
+    }
+
+    @Override
+    public List<Class< ? extends Annotation>> getTypeDelegatedAnnotationTypes() {
+        return annotations;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,73 @@
+/*
+ * 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.codegen.processor.node;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+
+
+public class ShortCircuitData extends TemplateMethod {
+
+    private ShortCircuitData genericShortCircuitMethod;
+    private final String valueName;
+
+    public ShortCircuitData(TemplateMethod template, String valueName) {
+        super(template);
+        this.valueName = valueName;
+    }
+
+    public String getValueName() {
+        return valueName;
+    }
+
+    public void setGenericShortCircuitMethod(ShortCircuitData genericShortCircuitMethod) {
+        this.genericShortCircuitMethod = genericShortCircuitMethod;
+    }
+
+    public boolean isGeneric() {
+        return genericShortCircuitMethod == null;
+    }
+
+    public ShortCircuitData getGeneric() {
+        if (isGeneric()) {
+            return this;
+        } else {
+            return genericShortCircuitMethod;
+        }
+    }
+
+    public boolean isCompatibleTo(SpecializationData specialization) {
+        if (isGeneric() && specialization.isGeneric()) {
+            return true;
+        }
+
+        for (ActualParameter param : getParameters()) {
+            ParameterSpec paramSpec = param.getSpecification();
+            ActualParameter specializationParam = specialization.findParameter(paramSpec.getName());
+            if (!Utils.typeEquals(param.getActualType(), specializationParam.getActualType())) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,80 @@
+/*
+ * 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.codegen.processor.node;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind;
+import com.oracle.truffle.codegen.processor.template.*;
+
+
+public class ShortCircuitParser extends MethodParser<ShortCircuitData> {
+
+    private final Set<String> shortCircuitValues;
+
+    public ShortCircuitParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+
+        shortCircuitValues = new HashSet<>();
+        NodeFieldData[] shortCircuitFields = node.filterFields(null, ExecutionKind.SHORT_CIRCUIT);
+        for (NodeFieldData field : shortCircuitFields) {
+            shortCircuitValues.add(field.getName());
+        }
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        String shortCircuitValue = Utils.getAnnotationValueString(mirror, "value");
+
+        if (!shortCircuitValues.contains(shortCircuitValue)) {
+            getContext().getLog().error(method, mirror, "Invalid short circuit value %s.", shortCircuitValue);
+            return null;
+        }
+
+        return createDefaultMethodSpec(shortCircuitValue);
+    }
+
+    @Override
+    protected ParameterSpec createReturnParameterSpec() {
+        return new ParameterSpec("has", getContext().getType(boolean.class), false);
+    }
+
+    @Override
+    public ShortCircuitData create(TemplateMethod method) {
+        String shortCircuitValue = Utils.getAnnotationValueString(method.getMarkerAnnotation(), "value");
+        assert shortCircuitValue != null;
+        assert shortCircuitValues.contains(shortCircuitValue);
+        return new ShortCircuitData(method, shortCircuitValue);
+    }
+
+    @Override
+    public Class< ? extends Annotation> getAnnotationType() {
+        return ShortCircuit.class;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,130 @@
+/*
+ * 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.codegen.processor.node;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.template.*;
+
+public class SpecializationData extends TemplateMethod {
+
+    private final int order;
+    private final boolean generic;
+    private final boolean uninitialized;
+    private final SpecializationThrowsData[] exceptions;
+    private SpecializationGuardData[] guards;
+    private ShortCircuitData[] shortCircuits;
+
+    private NodeData node;
+
+    public SpecializationData(TemplateMethod template, int order, SpecializationThrowsData[] exceptions) {
+        super(template);
+        this.order = order;
+        this.generic = false;
+        this.uninitialized = false;
+        this.exceptions = exceptions;
+
+        for (SpecializationThrowsData exception : exceptions) {
+            exception.setSpecialization(this);
+        }
+    }
+
+    public SpecializationData(TemplateMethod template, boolean generic, boolean uninitialized) {
+        super(template);
+        this.order = Specialization.DEFAULT_ORDER;
+        this.generic = generic;
+        this.uninitialized = uninitialized;
+        this.exceptions = new SpecializationThrowsData[0];
+        this.guards = new SpecializationGuardData[0];
+    }
+
+    public NodeData getNode() {
+        return node;
+    }
+
+    public void setNode(NodeData node) {
+        this.node = node;
+    }
+
+    public void setGuards(SpecializationGuardData[] guards) {
+        this.guards = guards;
+    }
+
+    public int getOrder() {
+        return order;
+    }
+
+    public boolean isGeneric() {
+        return generic;
+    }
+
+    public boolean isUninitialized() {
+        return uninitialized;
+    }
+
+    public SpecializationThrowsData[] getExceptions() {
+        return exceptions;
+    }
+
+    public SpecializationGuardData[] getGuards() {
+        return guards;
+    }
+
+    public void setShortCircuits(ShortCircuitData[] shortCircuits) {
+        this.shortCircuits = shortCircuits;
+    }
+
+    public ShortCircuitData[] getShortCircuits() {
+        return shortCircuits;
+    }
+
+    public SpecializationData findNextSpecialization() {
+        SpecializationData[] specializations = node.getSpecializations();
+        for (int i = 0; i < specializations.length - 1; i++) {
+            if (specializations[i] == this) {
+                return specializations[i + 1];
+            }
+        }
+        return null;
+    }
+
+    public boolean hasDynamicGuards() {
+        for (SpecializationGuardData guard : getGuards()) {
+            if (guard.isOnExecution()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public ActualParameter getPreviousParam(ActualParameter searchParam) {
+        ActualParameter prev = null;
+        for (ActualParameter param : getParameters()) {
+            if (param == searchParam) {
+                return prev;
+            }
+            prev = param;
+        }
+        return prev;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationGuardData.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.node;
+
+import com.oracle.truffle.codegen.processor.typesystem.*;
+
+public class SpecializationGuardData {
+
+    private final String guardMethod;
+    private final boolean onSpecialization;
+    private final boolean onExecution;
+
+    private GuardData guardDeclaration;
+
+    public SpecializationGuardData(String guardMethod, boolean onSpecialization, boolean onExecution) {
+        this.guardMethod = guardMethod;
+        this.onSpecialization = onSpecialization;
+        this.onExecution = onExecution;
+    }
+
+    public String getGuardMethod() {
+        return guardMethod;
+    }
+
+    public boolean isOnExecution() {
+        return onExecution;
+    }
+
+    public boolean isOnSpecialization() {
+        return onSpecialization;
+    }
+
+    public void setGuardDeclaration(GuardData compatibleGuard) {
+        this.guardDeclaration = compatibleGuard;
+    }
+
+    public GuardData getGuardDeclaration() {
+        return guardDeclaration;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,63 @@
+/*
+ * 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.codegen.processor.node;
+
+import java.lang.annotation.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+
+
+public class SpecializationListenerParser extends MethodParser<TemplateMethod> {
+
+    private final MethodSpec specification;
+
+    public SpecializationListenerParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+        this.specification = createDefaultMethodSpec(null);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        return specification;
+    }
+
+    @Override
+    protected ParameterSpec createReturnParameterSpec() {
+        return new ParameterSpec("void", getContext().getType(void.class), false);
+    }
+
+    @Override
+    public TemplateMethod create(TemplateMethod method) {
+        return method;
+    }
+
+    @Override
+    public Class< ? extends Annotation> getAnnotationType() {
+        return SpecializationListener.class;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,174 @@
+/*
+ * 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.codegen.processor.node;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.typesystem.*;
+
+
+public class SpecializationMethodParser extends MethodParser<SpecializationData> {
+
+    private final MethodSpec specification;
+
+    public SpecializationMethodParser(ProcessorContext context, NodeData operation) {
+        super(context, operation);
+        this.specification = createDefaultMethodSpec(null);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        return specification;
+    }
+
+    public MethodSpec getSpecification() {
+        return specification;
+    }
+
+    @Override
+    public SpecializationData create(TemplateMethod method) {
+        return parseSpecialization(method);
+    }
+
+    @Override
+    public Class< ? extends Annotation> getAnnotationType() {
+        return Specialization.class;
+    }
+
+    private SpecializationData parseSpecialization(TemplateMethod method) {
+        int order = Utils.getAnnotationValueInt(method.getMarkerAnnotation(), "order");
+        if (order < 0 && order != Specialization.DEFAULT_ORDER) {
+            getContext().getLog().error(method.getMethod(), method.getMarkerAnnotation(), "Invalid order attribute %d. The value must be >= 0 or the default value.");
+            return null;
+        }
+
+        List<AnnotationMirror> exceptionDefs = Utils.collectAnnotations(getContext(), method.getMarkerAnnotation(), "exceptions", method.getMethod(), SpecializationThrows.class);
+        SpecializationThrowsData[] exceptionData = new SpecializationThrowsData[exceptionDefs.size()];
+        for (int i = 0; i < exceptionData.length; i++) {
+            AnnotationMirror mirror = exceptionDefs.get(i);
+            TypeMirror javaClass = Utils.getAnnotationValueType(mirror, "javaClass");
+            String transitionTo = Utils.getAnnotationValueString(mirror, "transitionTo");
+            exceptionData[i] = new SpecializationThrowsData(mirror, javaClass, transitionTo);
+
+            if (!Utils.canThrowType(method.getMethod().getThrownTypes(), javaClass)) {
+                getContext().getLog().error(method.getMethod(), "Method must specify a throws clause with the exception type '%s'.", Utils.getQualifiedName(javaClass));
+                return null;
+            }
+        }
+
+        Arrays.sort(exceptionData, new Comparator<SpecializationThrowsData>() {
+            @Override
+            public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) {
+                return Utils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass());
+            }
+        });
+        SpecializationData specialization = new SpecializationData(method, order, exceptionData);
+        boolean valid = true;
+        List<AnnotationMirror> guardDefs = Utils.collectAnnotations(getContext(), method.getMarkerAnnotation(), "guards", method.getMethod(), SpecializationGuard.class);
+        SpecializationGuardData[] guardData = new SpecializationGuardData[guardDefs.size()];
+        for (int i = 0; i < guardData.length; i++) {
+            AnnotationMirror guardMirror = guardDefs.get(i);
+            String guardMethod = Utils.getAnnotationValueString(guardMirror, "methodName");
+            boolean onSpecialization = Utils.getAnnotationValueBoolean(guardMirror, "onSpecialization");
+            boolean onExecution = Utils.getAnnotationValueBoolean(guardMirror, "onExecution");
+
+            if (!onSpecialization && !onExecution) {
+                String message = "Either onSpecialization, onExecution or both must be enabled.";
+                getContext().getLog().error(method.getMethod(), guardMirror, message);
+                valid = false;
+                continue;
+            }
+
+            guardData[i] = new SpecializationGuardData(guardMethod, onSpecialization, onExecution);
+
+            GuardData compatibleGuard = matchSpecializationGuard(guardMirror, specialization, guardData[i]);
+            if (compatibleGuard != null) {
+                guardData[i].setGuardDeclaration(compatibleGuard);
+            } else {
+                valid = false;
+            }
+        }
+
+        if (!valid) {
+            return null;
+        }
+
+        specialization.setGuards(guardData);
+
+        return specialization;
+    }
+
+    private GuardData matchSpecializationGuard(AnnotationMirror mirror, SpecializationData specialization, SpecializationGuardData specializationGuard)  {
+        List<GuardData> foundGuards = getNode().findGuards(specializationGuard.getGuardMethod());
+
+        GuardData compatibleGuard = null;
+        for (GuardData guardData : foundGuards) {
+            if (isGuardCompatible(specialization, guardData)) {
+                compatibleGuard = guardData;
+                break;
+            }
+        }
+
+        if (compatibleGuard == null) {
+            ParameterSpec returnTypeSpec = new ParameterSpec("returnValue", getContext().getType(boolean.class), false);
+            List<ParameterSpec> expectedParameterSpecs = new ArrayList<>();
+
+            for (ActualParameter param : specialization.getParameters()) {
+                ParameterSpec spec = param.getSpecification();
+                expectedParameterSpecs.add(new ParameterSpec(spec.getName(), param.getActualType(), false));
+            }
+            String expectedSignature = TemplateMethodParser.createExpectedSignature(specializationGuard.getGuardMethod(), returnTypeSpec, expectedParameterSpecs);
+            AnnotationValue value = Utils.getAnnotationValue(mirror, "methodName");
+            getContext().getLog().error(specialization.getMethod(), mirror, value, "No guard with signature '%s' found in type system.", expectedSignature);
+            return null;
+        }
+
+        return compatibleGuard;
+    }
+
+    private static boolean isGuardCompatible(SpecializationData specialization, GuardData guard) {
+        Iterator<ActualParameter> guardParameters = Arrays.asList(guard.getParameters()).iterator();
+        for (ActualParameter param : specialization.getParameters()) {
+            if (!guardParameters.hasNext()) {
+                return false;
+            }
+            ActualParameter guardParam = guardParameters.next();
+            if (!Utils.typeEquals(guardParam.getActualType(), param.getActualType())) {
+                return false;
+            }
+        }
+        if (guardParameters.hasNext()) {
+            return false;
+        }
+        return true;
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationThrowsData.java	Fri Jan 18 13:28:12 2013 +0100
@@ -0,0 +1,71 @@
+/*
+ * 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.codegen.processor.node;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class SpecializationThrowsData {
+
+    private final AnnotationMirror annotationMirror;
+    private final TypeMirror javaClass;
+    private final String transitionTo;
+    private SpecializationData specialization;
+
+    public SpecializationThrowsData(AnnotationMirror annotationMirror, TypeMirror javaClass, String transitionTo) {
+        this.annotationMirror = annotationMirror;
+        this.javaClass = javaClass;
+        this.transitionTo = transitionTo;
+    }
+
+
+    void setSpecialization(SpecializationData specialization) {
+        this.specialization = specialization;
+    }
+
+    public TypeMirror getJavaClass() {
+        return javaClass;
+    }
+
+    public SpecializationData getSpecialization() {
+        return specialization;
+    }
+
+    public AnnotationMirror getAnnotationMirror() {
+        return annotationMirror;
+    }
+
+    public String getTransitionToName() {
+        return transitionTo;
+    }
+
+    public SpecializationData getTransitionTo() {
+        for (SpecializationData s : specialization.getNode().getSpecializations()) {
+            if (s.getMethodName().equals(transitionTo)) {
+                return s;
+            }
+        }
+        return null;
+    }
+}
+
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/GenericParser.java	Thu Jan 17 17:21:16 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +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.codegen.processor.operation;
-
-import java.lang.annotation.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.api.codegen.*;
-import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.template.*;
-import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
-import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
-
-public class GenericParser extends OperationMethodParser<SpecializationData> {
-
-    public GenericParser(ProcessorContext context, OperationData operation) {
-        super(context, operation);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        return createDefaultMethodSpec(null);
-    }
-
-    @Override
-    protected ParameterSpec createValueParameterSpec(String valueName) {
-        return new ParameterSpec(valueName, getOperation().getTypeSystem().getGenericType(), Kind.EXECUTE, false);
-    }
-
-    @Override
-    protected ParameterSpec createReturnParameterSpec() {
-        return new ParameterSpec("returnValue", getOperation().getTypeSystem(), Kind.EXECUTE, false, Cardinality.ONE);
-    }
-
-    @Override
-    public SpecializationData create(TemplateMethod method) {
-        return new SpecializationData(method, true, false);
-    }
-
-    @Override
-    public Class< ? extends Annotation> getAnnotationType() {
-        return Generic.class;
-    }
-
-}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationCodeGenerator.java	Thu Jan 17 17:21:16 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,903 +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.codegen.processor.operation;
-
-import static com.oracle.truffle.codegen.processor.Utils.*;
-import static javax.lang.model.element.Modifier.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.ast.*;
-import com.oracle.truffle.codegen.processor.template.*;
-import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
-import com.oracle.truffle.codegen.processor.typesystem.*;
-
-public class OperationCodeGenerator extends CompilationUnitFactory<OperationData> {
-
-    private static final String OPERATION_FIELD_NAME =  "operation";
-
-    public OperationCodeGenerator(ProcessorContext context) {
-        super(context);
-    }
-
-    private TypeMirror getUnexpectedValueException() {
-        return getContext().getTruffleTypes().getUnexpectedValueException();
-    }
-
-    private static String operationClassName(OperationData operation) {
-        return Utils.getSimpleName(operation.getTemplateType().asType());
-    }
-
-    private static String factoryClassName(OperationData operation) {
-        return operationClassName(operation) + "Factory";
-    }
-
-    private static String nodeClassName(OperationData operation) {
-        String name = operationClassName(operation);
-        if (name.length() > 2 && name.endsWith("Op")) {
-            name = name.substring(0, name.length() - 2);
-        }
-        return name + "Node";
-    }
-
-    private static String nodeClassName(SpecializationData specialization) {
-        String name = "";
-        if (specialization.getOperation().getAllMethods().length > 1) {
-            name = specialization.getMethodName();
-            if (name.startsWith("do")) {
-                name = name.substring(2);
-            }
-        }
-        return name + nodeClassName(specialization.getOperation());
-    }
-
-    private static String nodeVariableName(ParameterSpec spec) {
-        if (spec.getKind() == Kind.EXECUTE) {
-            return spec.getName() + "Node";
-        }
-        return spec.getName();
-    }
-
-    private static String nodeVariableName(ActualParameter param) {
-        return nodeVariableName(param.getSpecification());
-    }
-
-    private static String valueVariableName(ParameterSpec spec) {
-        if (spec.getKind() == Kind.EXECUTE) {
-            return spec.getName() + "Value";
-        }
-        return spec.getName();
-    }
-
-    private static String valueVariableName(ActualParameter param) {
-        return valueVariableName(param.getSpecification());
-    }
-
-    public static String executeMethodName(TypeData type) {
-        if (type.isGeneric()) {
-            return "executeGeneric";
-        }
-        return "execute" + Utils.getSimpleName(type.getBoxedType());
-    }
-
-    private static EnumSet<Kind> kinds(Kind... values) {
-        EnumSet<Kind> result = EnumSet.noneOf(Kind.class);
-        for (Kind value : values) {
-            result.add(value);
-        }
-        return result;
-    }
-
-    private static void addNodeParameters(CodeExecutableElement method, OperationData operation, EnumSet<Kind> included) {
-        for (ParameterSpec spec : operation.getSpecification().getParameters()) {
-            if (included.contains(spec.getKind())) {
-                if (spec.getKind() == Kind.EXECUTE) {
-                    method.addParameter(new CodeVariableElement(operation.getTypeSystem().getNodeType(), nodeVariableName(spec)));
-                } else {
-                    method.addParameter(new CodeVariableElement(spec.getValueType(), nodeVariableName(spec)));
-                }
-            }
-        }
-        if (included.contains(Kind.CONSTRUCTOR_FIELD)) {
-            for (OperationFieldData field : operation.getConstructorFields()) {
-                method.addParameter(new CodeVariableElement(field.getJavaClass(), field.getName()));
-            }
-        }
-    }
-
-    private static void addValueParameters(CodeExecutableElement method, OperationData operation, EnumSet<Kind> included) {
-        for (ParameterSpec spec : operation.getSpecification().getParameters()) {
-            if (included.contains(spec.getKind())) {
-                method.addParameter(new CodeVariableElement(spec.getValueType(), valueVariableName(spec)));
-            }
-        }
-        if (included.contains(Kind.CONSTRUCTOR_FIELD)) {
-            for (OperationFieldData field : operation.getConstructorFields()) {
-                method.addParameter(new CodeVariableElement(field.getJavaClass(), field.getName()));
-            }
-        }
-    }
-
-    private static void addOperationFieldName(CodeTreeBuilder body, OperationData operation) {
-        if (!operation.isUseSingleton()) {
-            body.string(OPERATION_FIELD_NAME);
-        }
-    }
-
-    private static void addOperationVariable(Set<Modifier> modifiers, Element element, OperationData operation, CodeTypeElement operationGen) {
-        if (!operation.isUseSingleton()) {
-            TypeMirror type = findOperationType(operation, operationGen);
-            if (element instanceof CodeExecutableElement) {
-                ((CodeExecutableElement) element).addParameter(new CodeVariableElement(modifiers, type, OPERATION_FIELD_NAME));
-            } else if (element instanceof CodeTypeElement) {
-                ((CodeTypeElement) element).add(new CodeVariableElement(modifiers, type, OPERATION_FIELD_NAME));
-            }
-        }
-    }
-
-    private static void addNodeNames(CodeTreeBuilder body, OperationData operation, EnumSet<Kind> included) {
-        for (ParameterSpec spec : operation.getSpecification().getParameters()) {
-            if (included.contains(spec.getKind())) {
-                body.string(nodeVariableName(spec));
-            }
-        }
-        if (included.contains(Kind.CONSTRUCTOR_FIELD)) {
-            for (OperationFieldData field : operation.getConstructorFields()) {
-                body.string(field.getName());
-            }
-        }
-    }
-
-    private static void addValueNames(CodeTreeBuilder body, OperationData operation, EnumSet<Kind> included) {
-        for (ParameterSpec spec : operation.getSpecification().getParameters()) {
-            if (included.contains(spec.getKind())) {
-                body.string(valueVariableName(spec));
-            }
-        }
-        if (included.contains(Kind.CONSTRUCTOR_FIELD)) {
-            for (OperationFieldData field : operation.getConstructorFields()) {
-                body.string(field.getName());
-            }
-        }
-    }
-
-    private static void addValueNamesWithCasts(ProcessorContext context, CodeTreeBuilder body, SpecializationData specialization, EnumSet<Kind> included) {
-        for (ActualParameter spec : specialization.getParameters()) {
-            if (included.contains(spec.getSpecification().getKind())) {
-                TypeData typeData = spec.getActualTypeData(specialization.getOperation().getTypeSystem());
-                if (typeData.isGeneric()) {
-                    body.string(valueVariableName(spec));
-                } else {
-                    String methodName = TypeSystemCodeGenerator.asTypeMethodName(typeData);
-                    startCallTypeSystemMethod(context, body, specialization.getOperation(), methodName);
-                    body.string(valueVariableName(spec));
-                    body.end().end();
-                }
-            }
-        }
-    }
-
-    public static VariableElement findSingleton(ProcessorContext context, OperationData operation) {
-        TypeMirror type = context.findGeneratedClassBySimpleName(OperationCodeGenerator.genClassName(operation), operation);
-        return Utils.findDeclaredField(type, OperationCodeGenerator.singletonName(operation));
-    }
-
-    private static TypeMirror findOperationType(OperationData operation, CodeTypeElement operationGen) {
-        if (operation.hasExtensions()) {
-            // return generated type
-            return operationGen.asType();
-        } else {
-            // return default type
-            return operation.getTemplateType().asType();
-        }
-    }
-
-    private static String genClassName(OperationData operation) {
-        String name = getSimpleName(operation.getTemplateType());
-        return name + "Gen";
-    }
-
-    private static String singletonName(OperationData operation) {
-        return createConstantName(getSimpleName(operation.getTemplateType().asType()));
-    }
-
-    private static void startCallOperationMethod(CodeTreeBuilder body, OperationData operation, TemplateMethod method) {
-        body.startGroup();
-
-        if (operation.isUseSingleton()) {
-            body.string(singletonName(operation));
-            body.string(".").startCall(method.getMethodName());
-        } else {
-            body.string(OPERATION_FIELD_NAME);
-            body.string(".");
-            body.startCall(method.getMethodName());
-        }
-    }
-
-    private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body,  OperationData operation, String methodName) {
-        VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, operation.getTypeSystem());
-        assert singleton != null;
-
-        body.startGroup();
-        body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString());
-        body.string(".").startCall(methodName);
-    }
-
-    private static void emitGuards(ProcessorContext context, CodeTreeBuilder body, String prefix, SpecializationData specialization, boolean onSpecialization, boolean needsCast) {
-        // Implict guards based on method signature
-        String andOperator = prefix;
-        for (ActualParameter param : specialization.getParameters()) {
-            if (param.getSpecification().getKind() == Kind.EXECUTE && !param.getActualTypeData(specialization.getOperation().getTypeSystem()).isGeneric()) {
-                body.string(andOperator);
-                startCallTypeSystemMethod(context, body, specialization.getOperation(),
-                                TypeSystemCodeGenerator.isTypeMethodName(param.getActualTypeData(specialization.getOperation().getTypeSystem())));
-                body.string(valueVariableName(param));
-                body.end().end(); // call
-                andOperator = " && ";
-            }
-        }
-
-        if (specialization.getGuards().length > 0) {
-            // Explicitly specified guards
-            for (SpecializationGuardData guard : specialization.getGuards()) {
-                if ((guard.isOnSpecialization() && onSpecialization)
-                                || (guard.isOnExecution() && !onSpecialization)) {
-                    body.string(andOperator);
-
-                    if (guard.getGuardDeclaration().getOrigin() == specialization.getOperation()) {
-                        startCallOperationMethod(body, specialization.getOperation(), guard.getGuardDeclaration());
-                    } else {
-                        startCallTypeSystemMethod(context, body, specialization.getOperation(), guard.getGuardMethod());
-                    }
-
-                    if (needsCast) {
-                        addValueNamesWithCasts(context, body, specialization, kinds(Kind.EXECUTE, Kind.SHORT_CIRCUIT));
-                    } else {
-                        addValueNames(body, specialization.getOperation(), kinds(Kind.EXECUTE, Kind.SHORT_CIRCUIT));
-                    }
-                    body.end().end(); // call
-                    andOperator = " && ";
-                }
-            }
-        }
-    }
-
-    @Override
-    protected void createChildren(OperationData m) {
-        CodeTypeElement operationGen = null;
-        if (m.hasExtensions()) {
-            OperationGenFactory factory = new OperationGenFactory(context);
-            add(factory, m);
-            operationGen = (CodeTypeElement) factory.getElement();
-        }
-        if (m.generateFactory) {
-            add(new OperationNodeFactory(context, operationGen), m);
-        }
-    }
-
-    protected class OperationGenFactory extends ClassElementFactory<OperationData> {
-
-        public OperationGenFactory(ProcessorContext context) {
-            super(context);
-        }
-
-        @Override
-        protected CodeTypeElement create(OperationData operation) {
-            CodeTypeElement clazz = createClass(operation, modifiers(PUBLIC), genClassName(operation), operation.getTemplateType().asType(), false);
-
-            clazz.add(createConstructorUsingFields(modifiers(PUBLIC), clazz));
-
-            if (operation.getExtensionElements() != null) {
-                clazz.getEnclosedElements().addAll(operation.getExtensionElements());
-            }
-            return clazz;
-        }
-
-    }
-
-
-
-    protected class OperationNodeFactory extends ClassElementFactory<OperationData> {
-
-        private final CodeTypeElement operationGen;
-
-        public OperationNodeFactory(ProcessorContext context, CodeTypeElement operationGen) {
-            super(context);
-            this.operationGen = operationGen;
-        }
-
-        @Override
-        protected CodeTypeElement create(OperationData operation) {
-            CodeTypeElement clazz = createClass(operation, modifiers(PUBLIC, FINAL), factoryClassName(operation), null, false);
-
-            if (operation.isUseSingleton()) {
-                TypeMirror type = findOperationType(operation, operationGen);
-                CodeVariableElement singleton = new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), type, singletonName(operation));
-                clazz.add(singleton);
-                CodeTreeBuilder singletonInit = singleton.createInitBuilder();
-                singletonInit.startNew(type).end();
-            }
-
-            clazz.add(createConstructorUsingFields(modifiers(PRIVATE), clazz));
-            clazz.add(createCreateMethod(operation));
-            if (operation.getAllMethods().length > 1) {
-                clazz.add(createCreateSpecializedMethod(operation));
-            }
-            if (operation.needsRewrites()) {
-                clazz.add(createSpecializeMethod(operation));
-                clazz.add(createGeneratedGenericMethod(operation));
-            }
-
-            return clazz;
-        }
-
-        @Override
-        protected void createChildren(OperationData operation) {
-            for (SpecializationData specialization : operation.getAllMethods()) {
-                add(new SpecializationNodeFactory(context, operationGen), specialization);
-            }
-        }
-
-        private CodeExecutableElement createCreateMethod(OperationData operation) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), operation.getNodeType(), "create");
-            addNodeParameters(method, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE, Kind.CONSTRUCTOR_FIELD));
-
-            CodeTreeBuilder body = method.createBuilder();
-            body.startReturn();
-            if (operation.getAllMethods().length == 0) {
-                body.null_();
-            } else {
-                body.startNew(nodeClassName(operation.getAllMethods()[0]));
-                emitNewOperation(body, operation);
-                addNodeNames(body, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
-                body.end();
-            }
-            body.end();
-
-            return method;
-        }
-
-        private void emitNewOperation(CodeTreeBuilder body, OperationData operation) {
-            if (!operation.isUseSingleton()) {
-                body.startGroup();
-                if (operation.hasExtensions()) {
-                    body.startNew(genClassName(operation));
-                } else {
-                    body.startNew(operation.getTemplateType().asType());
-                }
-                addNodeNames(body, operation, kinds(Kind.CONSTRUCTOR_FIELD));
-                body.end();
-                body.end();
-            }
-        }
-
-        private CodeExecutableElement createCreateSpecializedMethod(OperationData operation) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), operation.getNodeType(), "createSpecialized");
-            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "specializationClass"));
-            addOperationVariable(modifiers(), method, operation, operationGen);
-            addNodeParameters(method, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
-
-            CodeTreeBuilder body = method.createBuilder();
-
-            boolean first = true;
-            for (TypeData type : operation.getTypeSystem().getTypes()) {
-                SpecializationData specialization = operation.findUniqueSpecialization(type);
-                if (specialization != null && !type.isGeneric()) {
-                    if (first) {
-                        body.startIf();
-                        first = false;
-                    } else {
-                        body.startElseIf();
-                    }
-                    body.string("specializationClass == ").type(type.getBoxedType()).string(".class").end().startBlock();
-                    body.startReturn().startNew(nodeClassName(specialization));
-                    addOperationFieldName(body, operation);
-                    addNodeNames(body, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
-                    body.end().end();
-                    body.end();
-                }
-            }
-            body.startReturn().startNew(nodeClassName(operation.getGenericSpecialization()));
-            addOperationFieldName(body, operation);
-            addNodeNames(body, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
-            body.end().end();
-            return method;
-        }
-
-        private CodeExecutableElement createSpecializeMethod(OperationData operation) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), operation.getNodeType(), "specialize");
-            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState"));
-            addOperationVariable(modifiers(), method, operation, operationGen);
-            addValueParameters(method, operation, kinds(Kind.EXECUTE));
-            addNodeParameters(method, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
-
-            CodeTreeBuilder body = method.createBuilder();
-            body.startStatement().string("boolean allowed = (minimumState == ").string(nodeClassName(operation.getAllMethods()[0])).string(".class)").end();
-
-            for (int i = 1; i < operation.getAllMethods().length; i++) {
-                SpecializationData specialization = operation.getAllMethods()[i];
-                body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeClassName(specialization)).string(".class)").end();
-
-                if (specialization.isGeneric()) {
-                    body.startIf().string("allowed").end().startBlock();
-                } else {
-                    body.startIf().string("allowed");
-                    emitGuards(getContext(), body, " && ", specialization, true, true);
-                    body.end().startBlock();
-                }
-                body.startReturn().startNew(nodeClassName(specialization));
-
-                addOperationFieldName(body, operation);
-                addNodeNames(body, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
-                body.end().end();
-                body.end(); // block
-            }
-            body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end();
-
-            return method;
-        }
-
-
-        private void emitInvokeDoMethod(CodeTreeBuilder builder, SpecializationData specialization) {
-            if (specialization.getExceptions().length > 0) {
-                builder.startTryBlock();
-            }
-
-            builder.startReturn();
-            startCallOperationMethod(builder, specialization.getOperation(), specialization);
-            for (ActualParameter param : specialization.getParameters()) {
-                boolean needsCast = param.getSpecification().getKind() == Kind.EXECUTE && !param.getActualTypeData(specialization.getOperation().getTypeSystem()).isGeneric();
-                if (needsCast) {
-                    startCallTypeSystemMethod(getContext(), builder, specialization.getOperation(), TypeSystemCodeGenerator.asTypeMethodName(param.getActualTypeData(specialization.getOperation().getTypeSystem())));
-                }
-                builder.string(valueVariableName(param));
-                if (needsCast) {
-                    builder.end().end();
-                }
-            }
-            builder.end().end(); // start call operation
-            builder.end(); // return
-
-            if (specialization.getExceptions().length > 0) {
-                for (SpecializationThrowsData exception : specialization.getExceptions()) {
-                    builder.end().startCatchBlock(exception.getJavaClass(), "ex");
-                    emitInvokeDoMethod(builder, exception.getTransitionTo());
-                }
-                builder.end();
-            }
-        }
-
-        private CodeExecutableElement createGeneratedGenericMethod(OperationData operation) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), operation.getGenericSpecialization().getReturnType().getActualType(), "generatedGeneric");
-            addOperationVariable(modifiers(), method, operation, operationGen);
-            addValueParameters(method, operation, kinds(Kind.SIGNATURE, Kind.EXECUTE, Kind.SHORT_CIRCUIT, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
-
-            CodeTreeBuilder builder = method.createBuilder();
-            boolean ifStarted = false;
-            for (int i = 0; i < operation.getSpecializations().length; i++) {
-                SpecializationData specialization = operation.getSpecializations()[i];
-                if (specialization.isUninitialized()) {
-                    continue;
-                }
-                if (!specialization.isGeneric()) {
-                    if (!ifStarted) {
-                        builder.startIf();
-                        ifStarted = true;
-                    } else {
-                        builder.startElseIf();
-                    }
-                    emitGuards(getContext(), builder, "", specialization, false, true);
-                    builder.end().startBlock();
-                } else {
-                    builder.startElseBlock();
-                }
-
-                emitInvokeDoMethod(builder, specialization);
-                builder.end();
-            }
-            return method;
-        }
-    }
-
-    protected class SpecializationNodeFactory extends ClassElementFactory<SpecializationData> {
-
-        private CodeTypeElement operationGen;
-
-        public SpecializationNodeFactory(ProcessorContext context, CodeTypeElement operationGen) {
-            super(context);
-            this.operationGen = operationGen;
-        }
-
-        @Override
-        public CodeTypeElement create(SpecializationData specialization) {
-            OperationData operation = specialization.getOperation();
-            CodeTypeElement clazz = createClass(operation, modifiers(PRIVATE, STATIC, FINAL), nodeClassName(specialization), operation.getNodeType(), false);
-
-
-            CodeExecutableElement constructor = new CodeExecutableElement(modifiers(PROTECTED), null, clazz.getSimpleName().toString());
-            clazz.add(constructor);
-
-            CodeTreeBuilder builder = constructor.createBuilder();
-            builder.startStatement().startSuperCall();
-            addNodeNames(builder, operation, kinds(Kind.SUPER_ATTRIBUTE));
-            builder.end().end();
-
-            if (!operation.isUseSingleton()) {
-                addOperationVariable(modifiers(), constructor, operation, operationGen);
-                addOperationVariable(modifiers(PRIVATE, FINAL), clazz, operation, operationGen);
-                builder.startStatement();
-                builder.string("this.");
-                addOperationFieldName(builder, operation);
-                builder.string(" = ");
-                addOperationFieldName(builder, operation);
-                builder.end();
-            }
-            addNodeParameters(constructor, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
-
-
-            for (ParameterSpec spec : operation.getSpecification().getParameters()) {
-                String name = nodeVariableName(spec);
-
-                boolean isNodeAttribute = spec.getKind() == Kind.ATTRIBUTE && getContext().getEnvironment().getTypeUtils().isAssignable(spec.getValueType(), getContext().getTruffleTypes().getNode());
-                boolean isNodeArrayAttribute = spec.getKind() == Kind.ATTRIBUTE &&
-                                getContext().getEnvironment().getTypeUtils().isAssignable(spec.getValueType(), getContext().getTruffleTypes().getNodeArray());
-                if (spec.getKind() == Kind.EXECUTE || isNodeAttribute || isNodeArrayAttribute) {
-                    CodeVariableElement field = new CodeVariableElement(modifiers(PRIVATE), operation.getTypeSystem().getNodeType(), name);
-                    clazz.add(field);
-                    field.addAnnotationMirror(new CodeAnnotationMirror((DeclaredType) getContext().getTruffleTypes().getStableAnnotation()));
-                    if (isNodeArrayAttribute) {
-                        field.addAnnotationMirror(new CodeAnnotationMirror((DeclaredType) getContext().getTruffleTypes().getContentStableAnnotation()));
-                    }
-                    builder.startStatement().string("this.").string(name).string(" = adoptChild(").string(name).string(")").end();
-                } else if (spec.getKind() == Kind.ATTRIBUTE) {
-                    clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), spec.getValueType(), name));
-                    builder.startStatement().string("this.").string(name).string(" = ").string(name).end();
-                }
-            }
-
-            TypeSystemData typeSystem = operation.getTypeSystem();
-            for (TypeData type : typeSystem.getTypes()) {
-                CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), executeMethodName(type));
-                clazz.add(method);
-                addValueParameters(method, operation, kinds(Kind.SIGNATURE));
-                if (!type.isGeneric()) {
-                    method.addThrownType(getUnexpectedValueException());
-                }
-
-                if (specialization.getReturnType().getActualTypeData(typeSystem) == type) {
-                    buildFunctionalExecuteMethod(method.createBuilder(), operation, specialization);
-                } else {
-                    buildCastingExecuteMethod(method.createBuilder(), operation, specialization, type);
-                }
-            }
-
-            if (typeSystem.getVoidType() != null)  {
-                CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), typeSystem.getVoidType().getPrimitiveType(), executeMethodName(typeSystem.getVoidType()));
-                addValueParameters(method, operation, kinds(Kind.SIGNATURE));
-                buildCastingExecuteMethod(method.createBuilder(), operation, specialization, typeSystem.getVoidType());
-                clazz.add(method);
-            }
-
-            if (operation.needsRewrites() && !specialization.isGeneric() && !specialization.isUninitialized()) {
-                buildSpecializeStateMethod(clazz, operation);
-            }
-            buildSpecializeClassMethod(clazz, operation);
-
-            return clazz;
-        }
-
-        private void buildCastingExecuteMethod(CodeTreeBuilder builder, OperationData operation, SpecializationData specialization, TypeData type) {
-            if (!type.isVoid()) {
-                builder.startStatement().type(specialization.getReturnType().getActualType()).string(" result").end();
-            }
-
-            boolean needsTry = !specialization.getReturnType().getActualTypeData(operation.getTypeSystem()).isGeneric();
-            if (needsTry) {
-                builder.startTryBlock();
-            }
-
-            builder.startStatement();
-            if (!type.isVoid()) {
-                builder.string("result = ");
-            }
-            builder.startCall(executeMethodName(specialization.getReturnType().getActualTypeData(operation.getTypeSystem()))).string("frame").end();
-            builder.end(); // statement
-
-            if (needsTry) {
-                builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
-
-                if (!type.isVoid()) {
-                    builder.startReturn();
-                    if (!type.isGeneric()) {
-                        startCallTypeSystemMethod(getContext(), builder, operation, TypeSystemCodeGenerator.expectTypeMethodName(type));
-                    }
-
-                    builder.string("ex.getResult()");
-
-                    if (!type.isGeneric()) {
-                        builder.end().end();
-                    }
-                    builder.end(); // return
-                } else {
-                    builder.string("// ignore").newLine();
-                }
-            }
-            builder.end(); // try/catch
-
-            if (!type.isVoid()) {
-                builder.startReturn();
-                if (!type.isGeneric()) {
-                    startCallTypeSystemMethod(getContext(), builder, operation, TypeSystemCodeGenerator.expectTypeMethodName(type));
-                }
-                builder.string("result");
-                if (!type.isGeneric()) {
-                    builder.end().end();
-                }
-                builder.end(); // return
-            }
-        }
-
-        private void buildFunctionalExecuteMethod(CodeTreeBuilder builder, OperationData operation, SpecializationData specialization) {
-            ActualParameter previousShortCircuitParameter = null;
-            for (ActualParameter param : specialization.getParameters()) {
-                if (param.getSpecification().getKind() != Kind.EXECUTE) {
-                    // Nothing to do.
-                } else if (param.getActualTypeData(operation.getTypeSystem()).isGeneric()) {
-                    buildGenericValueExecute(builder, operation, param, null);
-                } else {
-                    buildSpecializedValueExecute(builder, operation, specialization, param);
-                }
-
-                assert param.getSpecification().getKind() == Kind.SHORT_CIRCUIT || previousShortCircuitParameter == null;
-            }
-
-            if (specialization.hasDynamicGuards()) {
-                builder.startIf();
-                emitGuards(getContext(), builder, "", specialization, false, false);
-                builder.end().startBlock();
-            }
-            if (specialization.getExceptions().length > 0) {
-                builder.startTryBlock();
-            }
-
-            if (specialization.isUninitialized() && operation.needsRewrites()) {
-                for (TemplateMethod listener : operation.getSpecializationListeners()) {
-                    builder.startStatement();
-                    startCallOperationMethod(builder, operation, listener);
-                    for (ActualParameter param : listener.getParameters()) {
-                        builder.string(valueVariableName(param));
-                    }
-                    builder.end().end();
-                    builder.end(); // statement
-                }
-
-                builder.startStatement();
-                builder.startCall("replace");
-                builder.startCall(factoryClassName(operation), "specialize");
-                builder.typeLiteral(builder.getRoot().getEnclosingClass().asType());
-                addOperationFieldName(builder, operation);
-                addValueNames(builder, operation, kinds(Kind.EXECUTE));
-                addNodeNames(builder, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
-                builder.end().end().end();
-            }
-
-            if ((specialization.isUninitialized() || specialization.isGeneric()) && operation.needsRewrites()) {
-                builder.startReturn().startCall(factoryClassName(specialization.getOperation()), "generatedGeneric");
-                addOperationFieldName(builder, operation);
-                addValueNames(builder, operation, kinds(Kind.SIGNATURE, Kind.EXECUTE, Kind.SHORT_CIRCUIT, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
-                builder.end().end();
-            } else {
-                builder.startReturn();
-
-                if (specialization.isUninitialized()) {
-                    startCallOperationMethod(builder, specialization.getOperation(), specialization.getOperation().getGenericSpecialization());
-                } else {
-                    startCallOperationMethod(builder, specialization.getOperation(), specialization);
-                }
-                for (ActualParameter param : specialization.getParameters()) {
-                    builder.string(valueVariableName(param));
-                }
-                builder.end().end(); // operation call
-                builder.end(); // return
-            }
-
-            if (specialization.getExceptions().length > 0) {
-                for (SpecializationThrowsData exception : specialization.getExceptions()) {
-                    builder.end().startCatchBlock(exception.getJavaClass(), "ex");
-                    buildThrowSpecialize(builder, operation, exception.getTransitionTo(), null);
-                }
-                builder.end();
-            }
-            if (specialization.hasDynamicGuards()) {
-                builder.end().startElseBlock();
-                buildThrowSpecialize(builder, operation, specialization.findNextSpecialization(), null);
-                builder.end();
-            }
-        }
-
-        private void buildGenericValueExecute(CodeTreeBuilder builder, OperationData operation, ActualParameter param, ParameterSpec exceptionSpec) {
-            boolean shortCircuit = startShortCircuit(builder, operation.getGenericSpecialization(),
-                            operation.getGenericSpecialization().findParameter(param.getSpecification().getName()), exceptionSpec);
-
-            builder.startStatement();
-            if (!shortCircuit) {
-                builder.type(operation.getTypeSystem().getGenericType());
-                builder.string(" ");
-            }
-            builder.string(valueVariableName(param));
-            builder.string(" = ").startCall(nodeVariableName(param), executeMethodName(operation.getTypeSystem().getGenericTypeData())).string("frame").end();
-            builder.end();
-
-            endShortCircuit(builder, shortCircuit);
-        }
-
-        private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization,
-                        ActualParameter forParam, ParameterSpec exceptionParam) {
-            ActualParameter shortCircuitParam = specialization.getPreviousParam(forParam);
-            if (shortCircuitParam == null || shortCircuitParam.getSpecification().getKind() != Kind.SHORT_CIRCUIT) {
-                return false;
-            }
-
-            int shortCircuitIndex = 0;
-            for (ActualParameter parameter : specialization.getParameters()) {
-                if (parameter.getSpecification().getKind() == Kind.SHORT_CIRCUIT) {
-                    if (parameter == shortCircuitParam) {
-                        break;
-                    }
-                    shortCircuitIndex++;
-                }
-            }
-
-            builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(shortCircuitParam.getSpecification().getName()).string(" = ");
-            ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex];
-
-            startCallOperationMethod(builder, specialization.getOperation(), shortCircuitData);
-            for (ActualParameter callParam : shortCircuitData.getParameters()) {
-                ParameterSpec spec = callParam.getSpecification();
-                if (spec.getKind() == Kind.EXECUTE || spec.getKind() == Kind.SHORT_CIRCUIT || spec.getKind() == Kind.SIGNATURE) {
-                    if (exceptionParam != null && callParam.getSpecification().getName().equals(exceptionParam.getName())) {
-                        builder.string("ex.getResult()");
-                    } else {
-                        builder.string(valueVariableName(spec));
-                    }
-                }
-            }
-            builder.end().end(); // call operation
-
-            builder.end(); // statement
-
-            builder.declaration(forParam.getActualType(), valueVariableName(forParam),
-                            CodeTreeBuilder.createBuilder().defaultValue(forParam.getActualType()));
-            builder.startIf().string(valueVariableName(shortCircuitParam)).end();
-            builder.startBlock();
-
-            return true;
-        }
-
-
-        private void endShortCircuit(CodeTreeBuilder builder, boolean shortCircuit) {
-            if (shortCircuit) {
-                builder.end();
-            }
-        }
-
-        private void buildSpecializedValueExecute(CodeTreeBuilder builder, OperationData operation, SpecializationData specialization, ActualParameter param) {
-            boolean shortCircuit = startShortCircuit(builder, specialization, param, null);
-
-            if (!shortCircuit) {
-                builder.startStatement().type(param.getActualType()).string(" ").string(valueVariableName(param)).end();
-            }
-
-            builder.startTryBlock();
-            builder.startStatement().string(valueVariableName(param)).string(" = ");
-            builder.startCall(nodeVariableName(param), executeMethodName(param.getActualTypeData(operation.getTypeSystem()))).string("frame").end();
-            builder.end();
-
-            builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
-            boolean execute = false;
-            for (ActualParameter exParam : specialization.getParameters()) {
-                if (exParam.getSpecification().getKind() != Kind.EXECUTE) {
-                    // Nothing to do.
-                } else if (execute) {
-                    buildGenericValueExecute(builder, operation, exParam, param.getSpecification());
-                } else if (exParam == param) {
-                    execute = true;
-                }
-            }
-
-            buildThrowSpecialize(builder, operation, specialization.findNextSpecialization(), param.getSpecification());
-            builder.end(); // catch block
-
-            endShortCircuit(builder, shortCircuit);
-            builder.newLine();
-        }
-
-        private void buildThrowSpecialize(CodeTreeBuilder builder, OperationData operation, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) {
-            builder.startThrow().startCall("specialize");
-            builder.string(nodeClassName(nextSpecialization) + ".class");
-            addValueNames(builder, operation, kinds(Kind.SIGNATURE));
-            for (ParameterSpec spec : operation.getSpecification().getParameters()) {
-                if (spec.getKind() == Kind.EXECUTE || spec.getKind() == Kind.SHORT_CIRCUIT) {
-                    if (spec == exceptionSpec) {
-                        builder.string("ex.getResult()");
-                    } else {
-                        builder.string(valueVariableName(spec));
-                    }
-                }
-            }
-            builder.end().end();
-        }
-
-        private void buildSpecializeStateMethod(CodeTypeElement clazz, OperationData operation) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), getUnexpectedValueException(), "specialize");
-            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState"));
-            addValueParameters(method, operation, kinds(Kind.SIGNATURE, Kind.EXECUTE, Kind.SHORT_CIRCUIT));
-            clazz.add(method);
-            CodeTreeBuilder builder = method.createBuilder();
-
-            for (TemplateMethod listener : operation.getSpecializationListeners()) {
-                builder.startStatement();
-                startCallOperationMethod(builder, operation, listener);
-                for (ActualParameter param : listener.getParameters()) {
-                    builder.string(valueVariableName(param));
-                }
-                builder.end().end();
-                builder.end(); // statement
-            }
-
-            builder.startStatement();
-            builder.startCall("replace");
-            builder.startCall(factoryClassName(operation), "specialize").string("minimumState");
-            addOperationFieldName(builder, operation);
-            addValueNames(builder, operation, kinds(Kind.EXECUTE));
-            addNodeNames(builder, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
-            builder.end().end().end();
-
-            builder.startReturn().startNew(getUnexpectedValueException()).startCall(factoryClassName(operation), "generatedGeneric");
-            addOperationFieldName(builder, operation);
-            addValueNames(builder, operation, kinds(Kind.SIGNATURE, Kind.EXECUTE, Kind.SHORT_CIRCUIT, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
-            builder.end().end().end();
-        }
-
-        private void buildSpecializeClassMethod(CodeTypeElement clazz, OperationData operation) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getContext().getType(void.class), "specialize");
-            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "specializationClass"));
-            if (!isDeclaredMethodInSuperType(clazz, method.getSimpleName().toString(), method.getParameterTypes())) {
-                return;
-            }
-            clazz.add(method);
-            CodeTreeBuilder builder = method.createBuilder();
-
-            builder.startStatement();
-            builder.startCall("replace");
-            builder.startCall(factoryClassName(operation), "createSpecialized").string("specializationClass");
-            addOperationFieldName(builder, operation);
-            addNodeNames(builder, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
-            builder.end().end().end();
-        }
-    }
-}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationData.java	Thu Jan 17 17:21:16 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +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.codegen.processor.operation;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.codegen.processor.template.*;
-import com.oracle.truffle.codegen.processor.typesystem.*;
-
-public class OperationData extends Template {
-
-    private final TypeSystemData typeSystem;
-    private final String[] values;
-    private final String[] shortCircuitValues;
-    private final OperationFieldData[] operationFields;
-    private final OperationFieldData[] constructorFields;
-    private final OperationFieldData[] superFields;
-    private final TypeMirror nodeType;
-
-    private MethodSpec specification;
-    private SpecializationData genericSpecialization;
-    private SpecializationData[] specializations;
-    private TemplateMethod[] specializationListeners;
-    private GuardData[] guards;
-
-    boolean generateFactory = true;
-
-    public OperationData(TypeElement templateType, AnnotationMirror templateTypeAnnotation,
-                    TypeSystemData typeSystem, TypeMirror nodeType,
-                    String[] values, String[] shortCircuitValues,
-                    OperationFieldData[] operationFields,
-                    OperationFieldData[] constructorFields,
-                    OperationFieldData[] superFields) {
-        super(templateType, templateTypeAnnotation);
-        this.nodeType = nodeType;
-        this.typeSystem = typeSystem;
-        this.values = values;
-        this.shortCircuitValues = shortCircuitValues;
-        this.operationFields = operationFields;
-        this.constructorFields = constructorFields;
-        this.superFields = superFields;
-    }
-
-    public boolean isUseSingleton() {
-        return constructorFields.length == 0;
-    }
-
-    public boolean hasExtensions() {
-        return !getExtensionElements().isEmpty();
-    }
-
-    public List<GuardData> findGuards(String name) {
-        List<GuardData> foundGuards = new ArrayList<>();
-        for (GuardData guardData : guards) {
-            if (guardData.getMethodName().equals(name)) {
-                foundGuards.add(guardData);
-            }
-        }
-        for (GuardData guardData : getTypeSystem().getGuards()) {
-            if (guardData.getMethodName().equals(name)) {
-                foundGuards.add(guardData);
-            }
-        }
-        return foundGuards;
-    }
-
-
-    void setGuards(GuardData[] guards) {
-        this.guards = guards;
-    }
-
-    void setSpecification(MethodSpec specification) {
-        this.specification = specification;
-    }
-
-    void setGenericSpecialization(SpecializationData genericSpecialization) {
-        this.genericSpecialization = genericSpecialization;
-    }
-
-    void setSpecializations(SpecializationData[] specializations) {
-        this.specializations = specializations;
-        for (SpecializationData specialization : specializations) {
-            specialization.setOperation(this);
-        }
-    }
-
-    void setSpecializationListeners(TemplateMethod[] specializationListeners) {
-        this.specializationListeners = specializationListeners;
-    }
-
-    public String[] getValues() {
-        return values;
-    }
-
-    public OperationFieldData[] getOperationFields() {
-        return operationFields;
-    }
-
-    public String[] getShortCircuitValues() {
-        return shortCircuitValues;
-    }
-
-    public TypeSystemData getTypeSystem() {
-        return typeSystem;
-    }
-
-    public TypeMirror getNodeType() {
-        return nodeType;
-    }
-
-    public SpecializationData[] getSpecializations() {
-        return specializations;
-    }
-
-    public SpecializationData getGenericSpecialization() {
-        return genericSpecialization;
-    }
-
-    public OperationFieldData[] getConstructorFields() {
-        return constructorFields;
-    }
-
-    public OperationFieldData[] getSuperFields() {
-        return superFields;
-    }
-
-    public MethodSpec getSpecification() {
-        return specification;
-    }
-
-    public SpecializationData[] getAllMethods() {
-        return specializations;
-    }
-
-    public boolean needsRewrites() {
-        boolean needsRewrites = getValues().length > 0 || getShortCircuitValues().length > 0;
-        needsRewrites &= specializations.length >= 2;
-        return needsRewrites;
-    }
-
-    public TemplateMethod[] getSpecializationListeners() {
-        return specializationListeners;
-    }
-
-    public GuardData[] getGuards() {
-        return guards;
-    }
-
-    public SpecializationData findUniqueSpecialization(TypeData type) {
-        SpecializationData result = null;
-        for (SpecializationData specialization : specializations) {
-            if (specialization.getReturnType().getActualTypeData(getTypeSystem()) == type) {
-                if (result != null) {
-                    // Result not unique;
-                    return null;
-                }
-                result = specialization;
-            }
-        }
-        return result;
-    }
-}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationFieldData.java	Thu Jan 17 17:21:16 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +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.codegen.processor.operation;
-
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.codegen.processor.*;
-
-public class OperationFieldData {
-
-    private final String name;
-    private final TypeMirror javaClass;
-
-    public OperationFieldData(String name, TypeMirror javaClass) {
-        this.name = name;
-        this.javaClass = javaClass;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public TypeMirror getJavaClass() {
-        return javaClass;
-    }
-
-    @Override
-    public String toString() {
-        return Utils.getSimpleName(javaClass);
-    }
-}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationMethodParser.java	Thu Jan 17 17:21:16 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +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.codegen.processor.operation;
-
-import java.util.*;
-
-import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.template.*;
-import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
-import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
-
-
-public abstract class OperationMethodParser<E extends TemplateMethod> extends TemplateMethodParser<E>{
-
-    private final OperationData operation;
-
-    public OperationMethodParser(ProcessorContext context, OperationData operation) {
-        super(context);
-        this.operation = operation;
-    }
-
-    public OperationData getOperation() {
-        return operation;
-    }
-
-    protected ParameterSpec createValueParameterSpec(String valueName) {
-        return new ParameterSpec(valueName, operation.getTypeSystem(),
-                        Kind.EXECUTE, false, Cardinality.ONE);
-    }
-
-    protected ParameterSpec createReturnParameterSpec() {
-        return createValueParameterSpec("operation");
-    }
-
-    protected final MethodSpec createDefaultMethodSpec(String shortCircuitName) {
-        List<ParameterSpec> defaultParameters = new ArrayList<>();
-        ParameterSpec frameSpec = new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), Kind.SIGNATURE, true);
-        defaultParameters.add(frameSpec);
-
-        for (String valueName : operation.getValues()) {
-            defaultParameters.add(createValueParameterSpec(valueName));
-        }
-
-        for (String valueName : operation.getShortCircuitValues()) {
-            if (shortCircuitName != null && valueName.equals(shortCircuitName)) {
-                break;
-            }
-
-            defaultParameters.add(new ParameterSpec(shortCircuitValueName(valueName),
-                            getContext().getType(boolean.class), Kind.SHORT_CIRCUIT, false));
-
-            defaultParameters.add(createValueParameterSpec(valueName));
-        }
-
-        for (OperationFieldData field : operation.getSuperFields()) {
-            defaultParameters.add(new ParameterSpec(field.getName(), field.getJavaClass(), Kind.SUPER_ATTRIBUTE, true));
-        }
-
-        for (OperationFieldData field : operation.getOperationFields()) {
-            defaultParameters.add(new ParameterSpec(field.getName(), field.getJavaClass(), Kind.ATTRIBUTE, false));
-        }
-
-        return new MethodSpec(createReturnParameterSpec(), defaultParameters);
-    }
-
-    private static String shortCircuitValueName(String valueName) {
-        return "has" + Utils.firstLetterUpperCase(valueName) + "Value";
-    }
-
-}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationParser.java	Thu Jan 17 17:21:16 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,569 +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.codegen.processor.operation;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.api.codegen.*;
-import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.ast.*;
-import com.oracle.truffle.codegen.processor.template.*;
-import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
-import com.oracle.truffle.codegen.processor.typesystem.*;
-
-public class OperationParser extends TemplateParser<OperationData> {
-
-    public OperationParser(ProcessorContext c) {
-        super(c);
-    }
-
-    @Override
-    public Class< ? extends Annotation> getAnnotationType() {
-        return com.oracle.truffle.api.codegen.Operation.class;
-    }
-
-    @Override
-    protected OperationData parse(Element element, AnnotationMirror templateTypeAnnotation) {
-        TypeElement templateType = (TypeElement) element;
-
-        if (!verifyTemplateType(templateType, templateTypeAnnotation)) {
-            return null;
-        }
-
-        TypeMirror typeSystemMirror = Utils.getAnnotationValueType(templateTypeAnnotation, "typeSystem");
-        final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSystemMirror, true);
-        if (typeSystem == null) {
-            log.error(templateType, templateTypeAnnotation, "Type system '%s' is invalid.", Utils.getQualifiedName(typeSystemMirror));
-            return null;
-        }
-
-        TypeMirror nodeType = Utils.getAnnotationValueType(templateTypeAnnotation, "baseClass");
-        if (Utils.typeEquals(nodeType, context.getTruffleTypes().getNode())) {
-            nodeType = typeSystem.getNodeType();
-        }
-
-        if (!Utils.isAssignable(nodeType, typeSystem.getNodeType())) {
-            log.error(templateType, templateTypeAnnotation,
-                            Utils.getAnnotationValue(templateTypeAnnotation, "baseClass"),
-                            "The baseClass does not extend the base class of the type system '%s'.", Utils.getQualifiedName(typeSystem.getNodeType()));
-            return null;
-        }
-
-        for (VariableElement field : ElementFilter.fieldsIn(templateType.getEnclosedElements())) {
-            if (!field.getModifiers().contains(Modifier.STATIC)
-                            && !field.getModifiers().contains(Modifier.FINAL)) {
-                log.error(field, "Field must be final.");
-                return null;
-            }
-        }
-
-
-        List<String> valueNames = Utils.getAnnotationValueList(templateTypeAnnotation, "values");
-        List<String> shortCircuitNames = Utils.getAnnotationValueList(templateTypeAnnotation, "shortCircuitValues");
-
-        List<String> names = new ArrayList<>();
-        names.addAll(valueNames);
-        names.addAll(shortCircuitNames);
-
-        List<AnnotationMirror> fieldAnnotations = Collections.emptyList(); // call collectionAnnotations instead if you want OperationField support enabled.
-        List<OperationFieldData> fields = new ArrayList<>();
-        for (AnnotationMirror fieldMirror : fieldAnnotations) {
-            String name = Utils.getAnnotationValueString(fieldMirror, "name");
-            TypeMirror javaClass = Utils.getAnnotationValueType(fieldMirror, "javaClass");
-            fields.add(new OperationFieldData(name, javaClass));
-            names.add(name);
-        }
-
-        List<OperationFieldData> constructorFields = parseConstructorFields(templateType, true);
-        if (constructorFields == null) {
-            return null;
-        }
-
-        List<OperationFieldData> superConstructorFields = parseConstructorFields(Utils.fromTypeMirror(nodeType), false);
-        if (superConstructorFields == null) {
-            return null;
-        }
-
-        List<OperationFieldData> protectedSuperFields = parseProtectedFields(Utils.fromTypeMirror(nodeType));
-        if (protectedSuperFields == null) {
-            return null;
-        }
-
-        List<OperationFieldData> matchedSuperFields = matchFields(superConstructorFields, protectedSuperFields);
-        if (matchedSuperFields == null) {
-            log.error(templateType, templateTypeAnnotation, Utils.getAnnotationValue(templateTypeAnnotation, "baseClass"),
-                            "The signature of the protected fields (%s) and the first constructor(%s) in %s does not match.",
-                            protectedSuperFields.toString(),
-                            superConstructorFields.toString(),
-                            Utils.getQualifiedName(nodeType));
-            return null;
-        }
-
-        for (OperationFieldData field : constructorFields) {
-            names.add(field.getName());
-        }
-
-        for (OperationFieldData field : matchedSuperFields) {
-            names.add(field.getName());
-        }
-
-        if (!verifyNames(templateType, templateTypeAnnotation, names)) {
-            return null;
-        }
-
-        OperationData operationData = new OperationData(templateType, templateTypeAnnotation, typeSystem, nodeType,
-                        valueNames.toArray(new String[valueNames.size()]),
-                        shortCircuitNames.toArray(new String[shortCircuitNames.size()]),
-                        fields.toArray(new OperationFieldData[fields.size()]),
-                        constructorFields.toArray(new OperationFieldData[constructorFields.size()]),
-                        matchedSuperFields.toArray(new OperationFieldData[matchedSuperFields.size()]));
-
-        if (!verifyExclusiveMethodAnnotation(templateType,
-                        Specialization.class, Generic.class, SpecializationListener.class, ShortCircuit.class, GuardCheck.class)) {
-            return noFactory(operationData);
-        }
-
-        operationData.setExtensionElements(getExtensionParser().parseAll(templateType));
-
-        List<SpecializationData> genericSpecializations = parseMethods(operationData, new GenericParser(context, operationData));
-        List<GuardData> guards = parseMethods(operationData, new GuardParser(context, operationData.getTypeSystem(), operationData));
-        operationData.setGuards(guards.toArray(new GuardData[guards.size()]));
-
-        SpecializationParser specializationParser = new SpecializationParser(context, operationData);
-        operationData.setSpecification(specializationParser.getSpecification());
-        List<SpecializationData> specializations = parseMethods(operationData, specializationParser);
-        List<ShortCircuitData> shortCircuits = parseMethods(operationData, new ShortCircuitParser(context, operationData));
-        List<TemplateMethod> listeners = parseMethods(operationData, new SpecializationListenerParser(context, operationData));
-
-        if (specializations == null || genericSpecializations == null || shortCircuits == null  || listeners == null || guards == null) {
-            return noFactory(operationData);
-        }
-
-
-        SpecializationData genericSpecialization = null;
-        if (genericSpecializations.size() > 1) {
-            for (SpecializationData generic : genericSpecializations) {
-                log.error(generic.getMethod(), "Only one method with @%s is allowed per operation.", Generic.class.getSimpleName());
-            }
-            return noFactory(operationData);
-        } else if (genericSpecializations.size() == 1) {
-            genericSpecialization = genericSpecializations.get(0);
-        }
-
-        if (specializations.size() > 1 && genericSpecialization == null) {
-            log.error(templateType, "Need a @%s method.", Generic.class.getSimpleName());
-            return noFactory(operationData);
-        }
-
-        Collections.sort(specializations, new Comparator<SpecializationData>() {
-            @Override
-            public int compare(SpecializationData o1, SpecializationData o2) {
-                return compareSpecialization(typeSystem, o1, o2);
-            }
-        });
-
-        List<SpecializationData> allSpecializations = new ArrayList<>(specializations);
-        if (genericSpecialization != null) {
-            allSpecializations.add(genericSpecialization);
-            TemplateMethod uninializedMethod = new TemplateMethod(genericSpecialization.getSpecification(), new CodeExecutableElement(context.getType(void.class), "doUninialized"),
-                            genericSpecialization.getMarkerAnnotation(), genericSpecialization.getReturnType(), genericSpecialization.getParameters());
-            allSpecializations.add(0, new SpecializationData(uninializedMethod, false, true));
-        }
-
-        // verify order is not ambiguous
-        verifySpecializationOrder(typeSystem, specializations);
-
-        operationData.setGenericSpecialization(genericSpecialization);
-        operationData.setSpecializations(allSpecializations.toArray(new SpecializationData[allSpecializations.size()]));
-        operationData.setSpecializationListeners(listeners.toArray(new TemplateMethod[listeners.size()]));
-
-        if (!assignShortCircuitsToSpecializations(operationData, allSpecializations, shortCircuits)) {
-            return null;
-        }
-
-        if (!verifyNamingConvention(specializations, "do")) {
-            return noFactory(operationData);
-        }
-
-        if (!verifyNamesUnique(specializations)) {
-            return noFactory(operationData);
-        }
-
-        if (!verifyNamingConvention(shortCircuits, "needs")) {
-            return noFactory(operationData);
-        }
-
-        if (!verifySpecializationThrows(typeSystem, specializations)) {
-            return noFactory(operationData);
-        }
-
-        return operationData;
-    }
-
-    private static List<OperationFieldData> matchFields(List<OperationFieldData> params,
-                    List<OperationFieldData> fields) {
-
-        if (params.size() != fields.size()) {
-            return null;
-        }
-
-        List<OperationFieldData> matchedFields = new ArrayList<>();
-        for (int i = 0; i < params.size(); i++) {
-            OperationFieldData param = params.get(i);
-            OperationFieldData field = fields.get(i);
-            if (!Utils.typeEquals(param.getJavaClass(), field.getJavaClass())) {
-                return null;
-            }
-            matchedFields.add(new OperationFieldData(field.getName(), param.getJavaClass()));
-        }
-
-        return matchedFields;
-    }
-
-    private static List<OperationFieldData> parseProtectedFields(Element element) {
-        List<OperationFieldData> opFields = new ArrayList<>();
-        List<VariableElement> fields = ElementFilter.fieldsIn(element.getEnclosedElements());
-        for (VariableElement var : fields) {
-            if (var.getModifiers().contains(Modifier.STATIC)) {
-                continue;
-            }
-
-            if (var.getModifiers().contains(Modifier.PROTECTED)) {
-                opFields.add(new OperationFieldData(var.getSimpleName().toString(), var.asType()));
-            }
-        }
-        return opFields;
-
-    }
-
-    private List<OperationFieldData> parseConstructorFields(Element element, boolean failOnMultipleConstructors) {
-        if (element == null) {
-            return Collections.emptyList();
-        }
-
-        List<ExecutableElement> constructors = ElementFilter.constructorsIn(element.getEnclosedElements());
-        ExecutableElement constructor = null;
-        if (constructors.size() > 1) {
-            if (failOnMultipleConstructors) {
-                for (ExecutableElement c : constructors) {
-                    log.error(c, "The Operation annotated class must not define multiple constructors.");
-                }
-                return null;
-            } else {
-                // take first constructor
-                constructor = constructors.get(0);
-            }
-        } else if (constructors.size() == 1) {
-            constructor = constructors.get(0);
-        }
-
-        List<OperationFieldData> constructorFields = new ArrayList<>();
-        if (constructor != null) {
-            for (VariableElement var : constructor.getParameters()) {
-                constructorFields.add(new OperationFieldData(var.getSimpleName().toString(), var.asType()));
-            }
-        }
-        return constructorFields;
-    }
-
-    private static OperationData noFactory(OperationData data) {
-        data.generateFactory = false;
-        return data;
-    }
-
-    private boolean verifySpecializationThrows(TypeSystemData typeSystem, List<SpecializationData> specializations) {
-        Map<String, SpecializationData> specializationMap = new HashMap<>();
-        for (SpecializationData spec : specializations) {
-            specializationMap.put(spec.getMethodName(), spec);
-        }
-        boolean valid = true;
-        for (SpecializationData sourceSpecialization : specializations) {
-            if (sourceSpecialization.getExceptions() != null) {
-                for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) {
-                    SpecializationData targetSpecialization = specializationMap.get(throwsData.getTransitionToName());
-                    AnnotationValue value = Utils.getAnnotationValue(throwsData.getAnnotationMirror(), "transitionTo");
-                    if (targetSpecialization == null) {
-                        log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), value,
-                                        "Specialization with name '%s' not found.", throwsData.getTransitionToName());
-                        valid = false;
-                    } else if (compareSpecialization(typeSystem, sourceSpecialization, targetSpecialization) >= 0) {
-                        log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), value,
-                                        "The order of the target specializalization must be higher than the source specialization.", throwsData.getTransitionToName());
-                        valid = false;
-                    }
-
-                    for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) {
-                        if (otherThrowsData != throwsData
-                                        && Utils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) {
-                            AnnotationValue javaClassValue = Utils.getAnnotationValue(throwsData.getAnnotationMirror(), "javaClass");
-                            log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), javaClassValue,
-                                            "Duplicate exception type.", throwsData.getTransitionToName());
-                            valid = false;
-                        }
-                    }
-                }
-            }
-        }
-        return valid;
-    }
-
-
-    private boolean assignShortCircuitsToSpecializations(OperationData operation,
-                    List<SpecializationData> specializations,
-                    List<ShortCircuitData> shortCircuits) {
-
-        Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(shortCircuits);
-
-        boolean valid = true;
-
-        for (String valueName : operation.getShortCircuitValues()) {
-            List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
-
-            if (availableCircuits == null || availableCircuits.isEmpty()) {
-                log.error(operation.getTemplateType(), operation.getTemplateTypeAnnotation(),
-                                "@%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) {
-                    log.error(circuit.getMethod(), circuit.getMarkerAnnotation(), "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, operation.getTypeSystem().getGenericType())) {
-                    genericCircuit = circuit;
-                    break;
-                }
-            }
-
-            if (genericCircuit == null) {
-                log.error(operation.getTemplateType(), operation.getTemplateTypeAnnotation(),
-                                "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 valid;
-        }
-
-        for (SpecializationData specialization : specializations) {
-            ShortCircuitData[] assignedShortCuts = new ShortCircuitData[operation.getShortCircuitValues().length];
-
-            for (int i = 0; i < operation.getShortCircuitValues().length; i++) {
-                List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(operation.getShortCircuitValues()[i]);
-
-                ShortCircuitData genericShortCircuit = null;
-                for (ShortCircuitData circuit : availableShortCuts) {
-                    if (circuit.isGeneric()) {
-                        genericShortCircuit = circuit;
-                    } else if (circuit.isCompatibleTo(specialization)) {
-                        assignedShortCuts[i] = circuit;
-                    }
-                }
-
-                if (assignedShortCuts[i] == null) {
-                    assignedShortCuts[i] = genericShortCircuit;
-                }
-            }
-            specialization.setShortCircuits(assignedShortCuts);
-        }
-        return true;
-    }
-
-    private static boolean isGenericShortCutMethod(TemplateMethod method, TypeMirror genericType) {
-        for (ActualParameter parameter : method.getParameters()) {
-            if (parameter.getSpecification().getKind() == Kind.EXECUTE) {
-                if (!Utils.typeEquals(genericType, parameter.getActualType())) {
-                    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 boolean verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) {
-        boolean valid = true;
-        for (int i = 0; i < methods.size(); i++) {
-            TemplateMethod m1 = methods.get(i);
-            if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
-                log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Naming convention: method name must start with '%s'.", prefix);
-                valid = false;
-            }
-        }
-        return valid;
-    }
-
-    private boolean verifyNamesUnique(List<? extends TemplateMethod> methods) {
-        boolean valid = true;
-        for (int i = 0; i < methods.size(); i++) {
-            TemplateMethod m1 = methods.get(i);
-            for (int j = i + 1; j < methods.size(); j++) {
-                TemplateMethod m2 = methods.get(j);
-
-                if (m1.getMethodName().equalsIgnoreCase(m2.getMethodName())) {
-                    log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Method name '%s' used multiple times", m1.getMethodName());
-                    log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Method name '%s' used multiple times", m1.getMethodName());
-                    return false;
-                }
-            }
-        }
-        return valid;
-    }
-
-    private boolean verifySpecializationOrder(TypeSystemData typeSystem, List<SpecializationData> specializations) {
-        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 = compareSpecializationWithoutOrder(typeSystem, m1, m2);
-
-                if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
-                    int specOrder = m1.getOrder() - m2.getOrder();
-                    if (specOrder == 0) {
-                        log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Order value %d used multiple times", m1.getOrder());
-                        log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Order value %d used multiple times", m1.getOrder());
-                        return false;
-                    } else if ((specOrder < 0 && inferredOrder > 0) || (specOrder > 0 && inferredOrder < 0)) {
-                        log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
-                        log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
-                        return false;
-                    }
-                } else if (inferredOrder == 0) {
-                    SpecializationData m = (m1.getOrder() == Specialization.DEFAULT_ORDER ? m1 : m2);
-                    log.error(m.getMethod(), m.getMarkerAnnotation(), "Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this.");
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    private static int compareSpecialization(TypeSystemData typeSystem, SpecializationData m1, SpecializationData m2) {
-        int result = compareSpecializationWithoutOrder(typeSystem, m1, m2);
-        if (result == 0) {
-            if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
-                return m1.getOrder() - m2.getOrder();
-            }
-        }
-        return result;
-    }
-
-    private static int compareSpecializationWithoutOrder(TypeSystemData typeSystem, SpecializationData m1, SpecializationData m2) {
-        if (m1.getSpecification() != m2.getSpecification()) {
-            throw new UnsupportedOperationException("Cannot compare two specializations with different specifications.");
-        }
-
-        int result = compareActualParameter(typeSystem, m1.getReturnType(), m2.getReturnType());
-
-        for (ParameterSpec spec : m1.getSpecification().getParameters()) {
-            ActualParameter p1 = m1.findParameter(spec);
-            ActualParameter p2 = m2.findParameter(spec);
-
-            if (p1 != null && p2 != null && !Utils.typeEquals(p1.getActualType(), p2.getActualType())) {
-                int typeResult = compareActualParameter(typeSystem, p1, p2);
-                if (result == 0) {
-                    result = typeResult;
-                } else if (Math.signum(result) != Math.signum(typeResult)) {
-                    // We cannot define an order.
-                    return 0;
-                }
-            }
-        }
-        return result;
-    }
-
-    private static int compareActualParameter(TypeSystemData typeSystem, ActualParameter p1, ActualParameter p2) {
-        int index1 = typeSystem.findType(p1.getActualType());
-        int index2 = typeSystem.findType(p2.getActualType());
-
-        assert index1 != index2;
-        assert !(index1 == -1 ^ index2 == -1);
-
-        return index1 - index2;
-    }
-
-    private boolean verifyNames(TypeElement element, AnnotationMirror mirror, List<String> names) {
-        boolean valid = true;
-
-        for (int i = 0; i < names.size(); i++) {
-            String name = names.get(i);
-            if (!JavaName.isValid(name)) {
-                log.error(element, mirror, "Name '%s' is not a valid java identifier.", name);
-                valid = false;
-            } else if (JavaName.isReserved(name)) {
-                log.error(element, mirror, "Name '%s' is a reserved java identifier.", name);
-                valid = false;
-            }
-            for (int j = i + 1; j < names.size(); j++) {
-                String otherName = names.get(j);
-                if (name.equalsIgnoreCase(otherName)) {
-                    log.error(element, mirror, "Name '%s' is not unique.", name);
-                    valid = false;
-                }
-            }
-        }
-        return valid;
-    }
-}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/ShortCircuitData.java	Thu Jan 17 17:21:16 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +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.codegen.processor.operation;
-
-import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.template.*;
-import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
-
-
-public class ShortCircuitData extends TemplateMethod {
-
-    private ShortCircuitData genericShortCircuitMethod;
-
-    private final String valueName;
-
-    public ShortCircuitData(TemplateMethod template, String valueName) {
-        super(template);
-        this.valueName = valueName;
-    }
-
-    public String getValueName() {
-        return valueName;
-    }
-
-    public void setGenericShortCircuitMethod(ShortCircuitData genericShortCircuitMethod) {
-        this.genericShortCircuitMethod = genericShortCircuitMethod;
-    }
-
-    public boolean isGeneric() {
-        return genericShortCircuitMethod == null;
-    }
-
-    public ShortCircuitData getGeneric() {
-        if (isGeneric()) {
-            return this;
-        } else {
-            return genericShortCircuitMethod;
-        }
-    }
-
-    public boolean isCompatibleTo(SpecializationData specialization) {
-        if (isGeneric() && specialization.isGeneric()) {
-            return true;
-        }
-
-        for (ActualParameter param : getParameters()) {
-            ParameterSpec paramSpec = param.getSpecification();
-            if (paramSpec.getKind() == Kind.EXECUTE) {
-                ActualParameter specializationParam = specialization.findParameter(paramSpec.getName());
-                if (!Utils.typeEquals(param.getActualType(), specializationParam.getActualType())) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/ShortCircuitParser.java	Thu Jan 17 17:21:16 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +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.codegen.processor.operation;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.api.codegen.*;
-import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.template.*;
-import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
-
-
-public class ShortCircuitParser extends OperationMethodParser<ShortCircuitData> {
-
-    private final Set<String> shortCircuitValues;
-
-    public ShortCircuitParser(ProcessorContext context, OperationData operation) {
-        super(context, operation);
-        shortCircuitValues = new HashSet<>(Arrays.asList(operation.getShortCircuitValues()));
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        String shortCircuitValue = Utils.getAnnotationValueString(mirror, "value");
-
-        if (!shortCircuitValues.contains(shortCircuitValue)) {
-            getContext().getLog().error(method, mirror, "Invalid short circuit value %s.", shortCircuitValue);
-            return null;
-        }
-
-        return createDefaultMethodSpec(shortCircuitValue);
-    }
-
-    @Override
-    protected ParameterSpec createReturnParameterSpec() {
-        return new ParameterSpec("has", getContext().getType(boolean.class), Kind.SHORT_CIRCUIT, false);
-    }
-
-    @Override
-    public ShortCircuitData create(TemplateMethod method) {
-        String shortCircuitValue = Utils.getAnnotationValueString(method.getMarkerAnnotation(), "value");
-        assert shortCircuitValue != null;
-        assert shortCircuitValues.contains(shortCircuitValue);
-        return new ShortCircuitData(method, shortCircuitValue);
-    }
-
-    @Override
-    public Class< ? extends Annotation> getAnnotationType() {
-        return ShortCircuit.class;
-    }
-
-}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationData.java	Thu Jan 17 17:21:16 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +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.codegen.processor.operation;
-
-import com.oracle.truffle.api.codegen.*;
-import com.oracle.truffle.codegen.processor.template.*;
-
-public class SpecializationData extends TemplateMethod {
-
-    private final int order;
-    private final boolean generic;
-    private final boolean uninitialized;
-    private final SpecializationThrowsData[] exceptions;
-    private SpecializationGuardData[] guards;
-    private ShortCircuitData[] shortCircuits;
-
-    private OperationData operation;
-
-    public SpecializationData(TemplateMethod template, int order, SpecializationThrowsData[] exceptions) {
-        super(template.getSpecification(), template.getMethod(), template.getMarkerAnnotation(), template.getReturnType(), template.getParameters());
-        this.order = order;
-        this.generic = false;
-        this.uninitialized = false;
-        this.exceptions = exceptions;
-
-        for (SpecializationThrowsData exception : exceptions) {
-            exception.setSpecialization(this);
-        }
-    }
-
-    public SpecializationData(TemplateMethod template, boolean generic, boolean uninitialized) {
-        super(template.getSpecification(), template.getMethod(), template.getMarkerAnnotation(), template.getReturnType(), template.getParameters());
-        this.order = Specialization.DEFAULT_ORDER;
-        this.generic = generic;
-        this.uninitialized = uninitialized;
-        this.exceptions = new SpecializationThrowsData[0];
-        this.guards = new SpecializationGuardData[0];
-    }
-
-    public void setOperation(OperationData operation) {
-        this.operation = operation;
-    }
-
-    void setGuards(SpecializationGuardData[] guards) {
-        this.guards = guards;
-    }
-
-    public OperationData getOperation() {
-        return operation;
-    }
-
-    public int getOrder() {
-        return order;
-    }
-
-    public boolean isGeneric() {
-        return generic;
-    }
-
-    public boolean isUninitialized() {
-        return uninitialized;
-    }
-
-    public SpecializationThrowsData[] getExceptions() {
-        return exceptions;
-    }
-
-    public SpecializationGuardData[] getGuards() {
-        return guards;
-    }
-
-    public void setShortCircuits(ShortCircuitData[] shortCircuits) {
-        this.shortCircuits = shortCircuits;
-    }
-
-    public ShortCircuitData[] getShortCircuits() {
-        return shortCircuits;
-    }
-
-    public SpecializationData findNextSpecialization() {
-        SpecializationData[] allMethods = operation.getAllMethods();
-        for (int i = 0; i < allMethods.length - 1; i++) {
-            if (allMethods[i] == this) {
-                return allMethods[i + 1];
-            }
-        }
-        throw new IllegalArgumentException();
-    }
-
-    public boolean hasDynamicGuards() {
-        for (SpecializationGuardData guard : getGuards()) {
-            if (guard.isOnExecution()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public ActualParameter getPreviousParam(ActualParameter searchParam) {
-        ActualParameter prev = null;
-        for (ActualParameter param : getParameters()) {
-            if (param == searchParam) {
-                return prev;
-            }
-            prev = param;
-        }
-        return prev;
-    }
-
-}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationGuardData.java	Thu Jan 17 17:21:16 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +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.codegen.processor.operation;
-
-import com.oracle.truffle.codegen.processor.typesystem.*;
-
-public class SpecializationGuardData {
-
-    private final String guardMethod;
-    private final boolean onSpecialization;
-    private final boolean onExecution;
-
-    private GuardData guardDeclaration;
-
-    public SpecializationGuardData(String guardMethod, boolean onSpecialization, boolean onExecution) {
-        this.guardMethod = guardMethod;
-        this.onSpecialization = onSpecialization;
-        this.onExecution = onExecution;
-    }
-
-    public String getGuardMethod() {
-        return guardMethod;
-    }
-
-    public boolean isOnExecution() {
-        return onExecution;
-    }
-
-    public boolean isOnSpecialization() {
-        return onSpecialization;
-    }
-
-    void setGuardDeclaration(GuardData compatibleGuard) {
-        this.guardDeclaration = compatibleGuard;
-    }
-
-    public GuardData getGuardDeclaration() {
-        return guardDeclaration;
-    }
-
-}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationListenerParser.java	Thu Jan 17 17:21:16 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +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.codegen.processor.operation;
-
-import java.lang.annotation.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.api.codegen.*;
-import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.template.*;
-import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
-
-
-public class SpecializationListenerParser extends OperationMethodParser<TemplateMethod> {
-
-    private final MethodSpec specification;
-
-    public SpecializationListenerParser(ProcessorContext context, OperationData operation) {
-        super(context, operation);
-        this.specification = createDefaultMethodSpec(null);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        return specification;
-    }
-
-    @Override
-    protected ParameterSpec createReturnParameterSpec() {
-        return new ParameterSpec("void", getContext().getType(void.class), Kind.ATTRIBUTE, false);
-    }
-
-    @Override
-    public TemplateMethod create(TemplateMethod method) {
-        return method;
-    }
-
-    @Override
-    public Class< ? extends Annotation> getAnnotationType() {
-        return SpecializationListener.class;
-    }
-
-}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationParser.java	Thu Jan 17 17:21:16 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +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.codegen.processor.operation;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.codegen.*;
-import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.template.*;
-import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
-import com.oracle.truffle.codegen.processor.typesystem.*;
-
-
-public class SpecializationParser extends OperationMethodParser<SpecializationData> {
-
-    private final MethodSpec specification;
-
-    public SpecializationParser(ProcessorContext context, OperationData operation) {
-        super(context, operation);
-        this.specification = createDefaultMethodSpec(null);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        return specification;
-    }
-    public MethodSpec getSpecification() {
-        return specification;
-    }
-
-    @Override
-    public SpecializationData create(TemplateMethod method) {
-        return parseSpecialization(method);
-    }
-
-    @Override
-    public Class< ? extends Annotation> getAnnotationType() {
-        return Specialization.class;
-    }
-
-    private SpecializationData parseSpecialization(TemplateMethod template) {
-        int order = Utils.getAnnotationValueInt(template.getMarkerAnnotation(), "order");
-        if (order < 0 && order != Specialization.DEFAULT_ORDER) {
-            getContext().getLog().error(template.getMethod(), template.getMarkerAnnotation(), "Invalid order attribute %d. The value must be >= 0 or the default value.");
-            return null;
-        }
-
-        List<AnnotationMirror> exceptionDefs = Utils.collectAnnotations(getContext(), template.getMarkerAnnotation(), "exceptions", template.getMethod(), SpecializationThrows.class);
-        SpecializationThrowsData[] exceptionData = new SpecializationThrowsData[exceptionDefs.size()];
-        for (int i = 0; i < exceptionData.length; i++) {
-            AnnotationMirror mirror = exceptionDefs.get(i);
-            TypeMirror javaClass = Utils.getAnnotationValueType(mirror, "javaClass");
-            String transitionTo = Utils.getAnnotationValueString(mirror, "transitionTo");
-            exceptionData[i] = new SpecializationThrowsData(mirror, javaClass, transitionTo);
-
-            if (!Utils.canThrowType(template.getMethod().getThrownTypes(), javaClass)) {
-                getContext().getLog().error(template.getMethod(), "Method must specify a throws clause with the exception type '%s'.", Utils.getQualifiedName(javaClass));
-                return null;
-            }
-        }
-
-        Arrays.sort(exceptionData, new Comparator<SpecializationThrowsData>() {
-            @Override
-            public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) {
-                return Utils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass());
-            }
-        });
-        SpecializationData specialization = new SpecializationData(template, order, exceptionData);
-
-        boolean valid = true;
-        List<AnnotationMirror> guardDefs = Utils.collectAnnotations(getContext(), template.getMarkerAnnotation(), "guards", template.getMethod(), SpecializationGuard.class);
-        SpecializationGuardData[] guardData = new SpecializationGuardData[guardDefs.size()];
-        for (int i = 0; i < guardData.length; i++) {
-            AnnotationMirror guardMirror = guardDefs.get(i);
-            String guardMethod = Utils.getAnnotationValueString(guardMirror, "methodName");
-            boolean onSpecialization = Utils.getAnnotationValueBoolean(guardMirror, "onSpecialization");
-            boolean onExecution = Utils.getAnnotationValueBoolean(guardMirror, "onExecution");
-
-            if (!onSpecialization && !onExecution) {
-                String message = "Either onSpecialization, onExecution or both must be enabled.";
-                getContext().getLog().error(template.getMethod(), guardMirror, message);
-                valid = false;
-                continue;
-            }
-
-            guardData[i] = new SpecializationGuardData(guardMethod, onSpecialization, onExecution);
-
-            GuardData compatibleGuard = matchSpecializationGuard(guardMirror, specialization, guardData[i]);
-            if (compatibleGuard != null) {
-                guardData[i].setGuardDeclaration(compatibleGuard);
-            } else {
-                valid = false;
-            }
-        }
-
-        if (!valid) {
-            return null;
-        }
-
-        specialization.setGuards(guardData);
-
-        return specialization;
-    }
-
-    private GuardData matchSpecializationGuard(AnnotationMirror mirror, SpecializationData specialization, SpecializationGuardData specializationGuard)  {
-        List<GuardData> foundGuards = getOperation().findGuards(specializationGuard.getGuardMethod());
-        GuardData compatibleGuard = null;
-        for (GuardData guardData : foundGuards) {
-            if (isGuardCompatible(specialization, guardData)) {
-                compatibleGuard = guardData;
-                break;
-            }
-        }
-
-        if (compatibleGuard == null) {
-            ParameterSpec returnTypeSpec = new ParameterSpec("returnValue", getContext().getType(boolean.class), Kind.ATTRIBUTE, false);
-            List<ParameterSpec> expectedParameterSpecs = new ArrayList<>();
-
-            for (ActualParameter param : filterGuardParameters(specialization)) {
-                ParameterSpec spec = param.getSpecification();
-                expectedParameterSpecs.add(new ParameterSpec(spec.getName(), param.getActualType(), Kind.ATTRIBUTE, false));
-            }
-            String expectedSignature = TemplateMethodParser.createExpectedSignature(specializationGuard.getGuardMethod(), returnTypeSpec, expectedParameterSpecs);
-            AnnotationValue value = Utils.getAnnotationValue(mirror, "methodName");
-            getContext().getLog().error(specialization.getMethod(), mirror, value, "No guard with signature '%s' found in type system.", expectedSignature);
-            return null;
-        }
-
-        return compatibleGuard;
-    }
-
-    private static boolean isGuardCompatible(SpecializationData specialization, GuardData guard) {
-        Iterator<ActualParameter> guardParameters = Arrays.asList(guard.getParameters()).iterator();
-        for (ActualParameter param : filterGuardParameters(specialization)) {
-            if (!guardParameters.hasNext()) {
-                return false;
-            }
-            ActualParameter guardParam = guardParameters.next();
-            if (!Utils.typeEquals(guardParam.getActualType(), param.getActualType())) {
-                return false;
-            }
-        }
-        if (guardParameters.hasNext()) {
-            return false;
-        }
-        return true;
-    }
-
-    private static List<ActualParameter> filterGuardParameters(SpecializationData specialization) {
-        List<ActualParameter> parameters = new ArrayList<>();
-        for (ActualParameter param : specialization.getParameters()) {
-            if (param.getSpecification().getKind() != Kind.EXECUTE
-                            && param.getSpecification().getKind() != Kind.SHORT_CIRCUIT) {
-                continue;
-            }
-            parameters.add(param);
-        }
-        return parameters;
-    }
-
-
-}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationThrowsData.java	Thu Jan 17 17:21:16 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +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.codegen.processor.operation;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public class SpecializationThrowsData {
-
-    private final AnnotationMirror annotationMirror;
-    private final TypeMirror javaClass;
-    private final String transitionTo;
-    private SpecializationData specialization;
-
-    public SpecializationThrowsData(AnnotationMirror annotationMirror, TypeMirror javaClass, String transitionTo) {
-        this.annotationMirror = annotationMirror;
-        this.javaClass = javaClass;
-        this.transitionTo = transitionTo;
-    }
-
-
-    void setSpecialization(SpecializationData specialization) {
-        this.specialization = specialization;
-    }
-
-    public TypeMirror getJavaClass() {
-        return javaClass;
-    }
-
-    public SpecializationData getSpecialization() {
-        return specialization;
-    }
-
-    public AnnotationMirror getAnnotationMirror() {
-        return annotationMirror;
-    }
-
-    public String getTransitionToName() {
-        return transitionTo;
-    }
-
-    public SpecializationData getTransitionTo() {
-        for (SpecializationData s : specialization.getOperation().getAllMethods()) {
-            if (s.getMethodName().equals(transitionTo)) {
-                return s;
-            }
-        }
-        throw new IllegalArgumentException();
-    }
-}
-
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java	Fri Jan 18 13:28:12 2013 +0100
@@ -45,6 +45,6 @@
     }
 
     public TypeData getActualTypeData(TypeSystemData typeSystem) {
-        return typeSystem.getTypes()[typeSystem.findType(actualType)];
+        return typeSystem.findTypeData(actualType);
     }
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java	Fri Jan 18 13:28:12 2013 +0100
@@ -44,6 +44,12 @@
     @Override
     protected abstract CodeTypeElement create(M m);
 
+
+    @Override
+    public CodeTypeElement getElement() {
+        return (CodeTypeElement) super.getElement();
+    }
+
     protected CodeExecutableElement createConstructorUsingFields(Set<Modifier> modifiers, CodeTypeElement clazz) {
         CodeExecutableElement method = new CodeExecutableElement(modifiers, null, clazz.getSimpleName().toString());
         CodeTreeBuilder builder = method.createBuilder();
@@ -81,6 +87,7 @@
         return method;
     }
 
+
     private static ExecutableElement findConstructor(TypeElement clazz) {
         List<ExecutableElement> constructors = ElementFilter.constructorsIn(clazz.getEnclosedElements());
         if (constructors.isEmpty()) {
@@ -90,6 +97,27 @@
         }
     }
 
+    protected CodeExecutableElement createSuperConstructor(TypeElement type, ExecutableElement element) {
+        if (element.getModifiers().contains(Modifier.PRIVATE)) {
+            return null;
+        }
+
+        CodeExecutableElement executable = CodeExecutableElement.clone(getContext().getEnvironment(), element);
+        executable.setReturnType(null);
+        executable.setSimpleName(CodeNames.of(type.getSimpleName().toString()));
+        CodeTreeBuilder b = executable.createBuilder();
+        b.startStatement();
+        b.startSuperCall();
+        for (VariableElement v : element.getParameters()) {
+            b.string(v.getSimpleName().toString());
+        }
+        b.end();
+        b.end();
+
+        return executable;
+    }
+
+
     protected CodeTypeElement createClass(Template model, Set<Modifier> modifiers, String simpleName, TypeMirror superType, boolean enumType) {
         TypeElement templateType = model.getTemplateType();
 
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CodeElementFactory.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CodeElementFactory.java	Fri Jan 18 13:28:12 2013 +0100
@@ -44,9 +44,12 @@
     protected void createChildren(M m) { }
 
     @SuppressWarnings("unchecked")
-    public final CodeElement<?> process(M m) {
+    public CodeElement<?> process(CodeElement parent, M m) {
         model = m;
         element = (CodeElement<? super Element>) create(model);
+        if (parent != null) {
+            parent.add(element);
+        }
         if (element != null) {
             createChildren(model);
         }
@@ -58,7 +61,7 @@
     }
 
     protected <MO, K extends Element> void add(CodeElementFactory<MO> factory, MO m) {
-        this.element.add(factory.process(m));
+        factory.process(this.element, m);
     }
 
     public ProcessorContext getContext() {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CompilationUnitFactory.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CompilationUnitFactory.java	Fri Jan 18 13:28:12 2013 +0100
@@ -37,6 +37,11 @@
     }
 
     @Override
+    public CodeCompilationUnit process(CodeElement parent, M m) {
+        return (CodeCompilationUnit) super.process(parent, m);
+    }
+
+    @Override
     protected abstract void createChildren(M m);
 
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java	Fri Jan 18 13:28:12 2013 +0100
@@ -22,17 +22,16 @@
  */
 package com.oracle.truffle.codegen.processor.template;
 
+import java.util.*;
+
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.node.*;
 import com.oracle.truffle.codegen.processor.typesystem.*;
 
 public class ParameterSpec {
 
-    public enum Kind {
-        EXECUTE, SIGNATURE, SUPER_ATTRIBUTE, ATTRIBUTE, CONSTRUCTOR_FIELD, SHORT_CIRCUIT
-    }
-
     public enum Cardinality {
         ONE, MULTIPLE;
     }
@@ -40,35 +39,49 @@
     private final String name;
     private final TypeMirror[] allowedTypes;
     private final TypeMirror valueType;
-    private final Kind kind;
     private final boolean optional;
     private final Cardinality cardinality;
 
-    public ParameterSpec(String name, TypeMirror[] allowedTypes, TypeMirror valueType, Kind kind, boolean optional, Cardinality cardinality) {
+    public ParameterSpec(String name, TypeMirror[] allowedTypes, TypeMirror valueType, boolean optional, Cardinality cardinality) {
         this.valueType = valueType;
         this.allowedTypes = allowedTypes;
         this.name = name;
-        this.kind = kind;
         this.optional = optional;
         this.cardinality = cardinality;
     }
 
-    public ParameterSpec(String name, TypeMirror singleFixedType, Kind kind, boolean optional) {
-        this(name, new TypeMirror[]{singleFixedType}, singleFixedType, kind, optional, Cardinality.ONE);
+    /** Type constructor. */
+    public ParameterSpec(String name, TypeMirror singleFixedType,  boolean optional) {
+        this(name, new TypeMirror[]{singleFixedType}, singleFixedType, optional, Cardinality.ONE);
+    }
+
+    /** Type system value constructor. */
+    public ParameterSpec(String name, TypeSystemData typeSystem, boolean optional, Cardinality cardinality) {
+        this(name, typeSystem.getPrimitiveTypeMirrors(), typeSystem.getGenericType(), optional, cardinality);
     }
 
-    public ParameterSpec(String name, TypeSystemData typeSystem, Kind kind, boolean optional, Cardinality cardinality) {
-        this(name, typeSystem.getPrimitiveTypeMirrors(), typeSystem.getGenericType(), kind, optional, cardinality);
+    /** Node value constructor. */
+    public ParameterSpec(String name, NodeData nodeData, boolean optional, Cardinality cardinality) {
+        this(name, nodeTypeMirrors(nodeData), nodeData.getTypeSystem().getGenericType(), optional, cardinality);
     }
 
+    private static TypeMirror[] nodeTypeMirrors(NodeData nodeData) {
+        List<TypeMirror> typeMirrors = new ArrayList<>();
+
+        for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) {
+            typeMirrors.add(typeData.getType().getPrimitiveType());
+        }
+
+        typeMirrors.add(nodeData.getTypeSystem().getGenericType());
+
+        return typeMirrors.toArray(new TypeMirror[typeMirrors.size()]);
+    }
+
+
     public final String getName() {
         return name;
     }
 
-    public Kind getKind() {
-        return kind;
-    }
-
     public final boolean isOptional() {
         return optional;
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java	Fri Jan 18 13:28:12 2013 +0100
@@ -26,13 +26,15 @@
 
 public class TemplateMethod {
 
+    private final Template template;
     private final MethodSpec specification;
     private final ExecutableElement method;
     private final AnnotationMirror markerAnnotation;
     private final ActualParameter returnType;
     private final ActualParameter[] parameters;
 
-    public TemplateMethod(MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType, ActualParameter[] parameters) {
+    public TemplateMethod(Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType, ActualParameter[] parameters) {
+        this.template = template;
         this.specification = specification;
         this.method = method;
         this.markerAnnotation = markerAnnotation;
@@ -41,6 +43,7 @@
     }
 
     public TemplateMethod(TemplateMethod method) {
+        this.template = method.template;
         this.specification = method.specification;
         this.method = method.method;
         this.markerAnnotation = method.markerAnnotation;
@@ -48,6 +51,9 @@
         this.parameters = method.parameters;
     }
 
+    public Template getTemplate() {
+        return template;
+    }
 
     public MethodSpec getSpecification() {
         return specification;
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -29,18 +29,41 @@
 
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
+import javax.lang.model.util.*;
 
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
 
-public abstract class TemplateMethodParser<E extends TemplateMethod> {
+public abstract class TemplateMethodParser<T extends Template, E extends TemplateMethod> {
 
     private final ProcessorContext context;
 
-    public TemplateMethodParser(ProcessorContext context) {
+    protected final T template;
+
+    private boolean emitErrors = true;
+    private boolean parseNullOnError = true;
+
+    public TemplateMethodParser(ProcessorContext context, T template) {
+        this.template = template;
         this.context = context;
     }
 
+    public boolean isEmitErrors() {
+        return emitErrors;
+    }
+
+    public void setParseNullOnError(boolean nullOnError) {
+        this.parseNullOnError = nullOnError;
+    }
+
+    public boolean isParseNullOnError() {
+        return parseNullOnError;
+    }
+
+    public void setEmitErrors(boolean emitErrors) {
+        this.emitErrors = emitErrors;
+    }
+
     public ProcessorContext getContext() {
         return context;
     }
@@ -49,9 +72,49 @@
 
     public abstract E create(TemplateMethod method);
 
-    public abstract Class<? extends Annotation> getAnnotationType();
+    public abstract boolean isParsable(ExecutableElement method);
+
+    public Class<? extends Annotation> getAnnotationType() {
+        return null;
+    }
+
+    public final List<E> parse(List<? extends Element> elements) {
+        List<ExecutableElement> methods = new ArrayList<>();
+        methods.addAll(ElementFilter.methodsIn(elements));
+
+        List<E> parsedMethods = new ArrayList<>();
+        boolean valid = true;
+        for (ExecutableElement method : methods) {
+            if (!isParsable(method)) {
+                continue;
+            }
 
-    public final E parse(ExecutableElement method, AnnotationMirror annotation, Template template) {
+            Class<? extends Annotation> annotationType = getAnnotationType();
+            AnnotationMirror mirror = null;
+            if (annotationType != null) {
+                mirror = Utils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType);
+            }
+
+            if (method.getModifiers().contains(Modifier.PRIVATE)) {
+                getContext().getLog().error(method, "Method must not be private.");
+                valid = false;
+                continue;
+            }
+
+            E parsedMethod = parse(method, mirror);
+            if (parsedMethod != null) {
+                parsedMethods.add(parsedMethod);
+            } else {
+                valid = false;
+            }
+        }
+        if (!valid && parseNullOnError) {
+            return null;
+        }
+        return parsedMethods;
+    }
+
+    private E parse(ExecutableElement method, AnnotationMirror annotation) {
         MethodSpec methodSpecification = createSpecification(method, annotation);
         if (methodSpecification == null) {
             return null;
@@ -63,13 +126,15 @@
 
         ActualParameter returnTypeMirror = resolveTypeMirror(returnTypeSpec, method.getReturnType(), template);
         if (returnTypeMirror == null) {
-            String expectedReturnType = createTypeSignature(returnTypeSpec, true);
-            String actualReturnType = Utils.getSimpleName(method.getReturnType());
+            if (isEmitErrors()) {
+                String expectedReturnType = createTypeSignature(returnTypeSpec, true);
+                String actualReturnType = Utils.getSimpleName(method.getReturnType());
 
-            String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
-                            createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
+                String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
+                                createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
 
-            context.getLog().error(method, annotation, message);
+                context.getLog().error(method, annotation, message);
+            }
             return null;
         }
 
@@ -93,13 +158,15 @@
                     specification = null;
                     continue;
                 } else if (!specification.isOptional()) {
-                    // non option type specification found -> argument missing
-                    String expectedType = createTypeSignature(specification, false);
+                    if (isEmitErrors()) {
+                        // non option type specification found -> argument missing
+                        String expectedType = createTypeSignature(specification, false);
 
-                    String message = String.format("Missing argument \"%s\".\nExpected signature: \n %s", expectedType,
-                                    createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
+                        String message = String.format("Missing argument \"%s\".\nExpected signature: \n %s", expectedType,
+                                        createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
 
-                    context.getLog().error(method, message);
+                        context.getLog().error(method, message);
+                    }
                     return null;
                 } else {
                     // specification is optional -> continue
@@ -116,13 +183,15 @@
                     continue;
                 }
 
-                String expectedReturnType = createTypeSignature(specification, false);
-                String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName();
+                if (isEmitErrors()) {
+                    String expectedReturnType = createTypeSignature(specification, false);
+                    String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName();
 
-                String message = String.format("The provided argument type \"%s\" does not match expected type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
-                                createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
+                    String message = String.format("The provided argument type \"%s\" does not match expected type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
+                                    createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
 
-                context.getLog().error(parameter, message);
+                    context.getLog().error(parameter, message);
+                }
                 return null;
             }
 
@@ -136,16 +205,18 @@
 
         if (variableIterator.hasNext()) {
             parameter = variableIterator.next();
-            String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName();
-            String message = String.format("No argument expected but found \"%s\".\nExpected signature: \n %s", actualReturnType,
-                            createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
+            if (isEmitErrors()) {
+                String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName();
+                String message = String.format("No argument expected but found \"%s\".\nExpected signature: \n %s", actualReturnType,
+                                createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
 
-            context.getLog().error(parameter, message);
+                context.getLog().error(parameter, message);
+            }
             return null;
         }
 
         ActualParameter[] paramMirrors = resolvedMirrors.toArray(new ActualParameter[resolvedMirrors.size()]);
-        return create(new TemplateMethod(methodSpecification, method, annotation, returnTypeMirror, paramMirrors));
+        return create(new TemplateMethod(template, methodSpecification, method, annotation, returnTypeMirror, paramMirrors));
     }
 
     private ActualParameter resolveTypeMirror(ParameterSpec specification, TypeMirror mirror, Template typeSystem) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -28,7 +28,6 @@
 import javax.lang.model.util.*;
 
 import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.api.element.*;
 import com.oracle.truffle.codegen.processor.ext.*;
 
 public abstract class TemplateParser<M extends Template> extends AbstractParser<M> {
@@ -92,42 +91,4 @@
         return valid;
     }
 
-    protected <E extends TemplateMethod> List<E> parseMethods(Template template, TemplateMethodParser<E> parser) {
-        TypeElement type = template.getTemplateType();
-
-        List<ExecutableElement> methods = new ArrayList<>();
-        methods.addAll(ElementFilter.methodsIn(type.getEnclosedElements()));
-        if (template.getExtensionElements() != null) {
-            for (WritableElement e : template.getExtensionElements()) {
-                if (e instanceof ExecutableElement) {
-                    methods.add((ExecutableElement) e);
-                }
-            }
-        }
-
-        List<E> parsedMethods = new ArrayList<>();
-        boolean valid = true;
-        for (ExecutableElement method : methods) {
-            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, parser.getAnnotationType());
-            if (mirror != null) {
-                if (method.getModifiers().contains(Modifier.PRIVATE)) {
-                    log.error(method, "Methods annotated with @%s must not be private.",  parser.getAnnotationType().getSimpleName());
-                    valid = false;
-                    continue;
-                }
-                E parsedMethod = parser.parse(method, mirror, template);
-                if (parsedMethod != null) {
-                    parsedMethods.add(parsedMethod);
-                } else {
-                    valid = false;
-                }
-            }
-        }
-        if (!valid) {
-            return null;
-        }
-        return parsedMethods;
-    }
-
-
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -31,30 +31,34 @@
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.template.*;
 import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
-import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
 
 
-public class GuardParser extends TypeSystemMethodParser<GuardData> {
+public class GuardParser extends TemplateMethodParser<Template, GuardData> {
 
-    private final Template origin;
+    private final TypeSystemData typeSystem;
 
-    public GuardParser(ProcessorContext context, TypeSystemData typeSystem, Template origin) {
-        super(context, typeSystem);
-        this.origin = origin;
+    public GuardParser(ProcessorContext context, Template template, TypeSystemData typeSystem) {
+        super(context, template);
+        this.typeSystem = typeSystem;
     }
 
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
         List<ParameterSpec> specs = new ArrayList<>();
-        specs.add(new ParameterSpec("value1", getTypeSystem(), Kind.EXECUTE, false, Cardinality.ONE));
-        specs.add(new ParameterSpec("valueN", getTypeSystem(), Kind.EXECUTE, false, Cardinality.MULTIPLE));
-        ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class), Kind.ATTRIBUTE, false);
+        specs.add(new ParameterSpec("value1", typeSystem, false, Cardinality.ONE));
+        specs.add(new ParameterSpec("valueN", typeSystem, false, Cardinality.MULTIPLE));
+        ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class), false);
         return new MethodSpec(returnTypeSpec, specs);
     }
 
     @Override
+    public boolean isParsable(ExecutableElement method) {
+        return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
+    }
+
+    @Override
     public GuardData create(TemplateMethod method) {
-        return new GuardData(method, origin);
+        return new GuardData(method, template);
     }
 
     @Override
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -31,7 +31,6 @@
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.template.*;
 import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
-import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
 
 
 class TypeCastParser extends TypeSystemMethodParser<TypeCastData> {
@@ -47,8 +46,8 @@
             return null;
         }
         List<ParameterSpec> specs = new ArrayList<>();
-        specs.add(new ParameterSpec("value", getTypeSystem(), Kind.EXECUTE, false, Cardinality.ONE));
-        ParameterSpec returnTypeSpec = new ParameterSpec("returnType", targetType.getPrimitiveType(), Kind.ATTRIBUTE, false);
+        specs.add(new ParameterSpec("value", getTypeSystem(), false, Cardinality.ONE));
+        ParameterSpec returnTypeSpec = new ParameterSpec("returnType", targetType.getPrimitiveType(), false);
         MethodSpec spec = new MethodSpec(returnTypeSpec, specs);
         return spec;
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -31,7 +31,6 @@
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.template.*;
 import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
-import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
 
 class TypeCheckParser extends TypeSystemMethodParser<TypeCheckData> {
 
@@ -46,8 +45,8 @@
             return null;
         }
         List<ParameterSpec> specs = new ArrayList<>();
-        specs.add(new ParameterSpec("value", getTypeSystem(), Kind.EXECUTE, false, Cardinality.ONE));
-        ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class), Kind.ATTRIBUTE, false);
+        specs.add(new ParameterSpec("value", getTypeSystem(), false, Cardinality.ONE));
+        ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class), false);
         MethodSpec spec = new MethodSpec(returnTypeSpec, specs);
         return spec;
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java	Fri Jan 18 13:28:12 2013 +0100
@@ -84,5 +84,11 @@
         }
         return Utils.typeEquals(boxedType, getTypeSystem().getVoidType().getBoxedType());
     }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + Utils.getSimpleName(primitiveType) + "]";
+    }
+
 }
 
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java	Fri Jan 18 13:28:12 2013 +0100
@@ -36,22 +36,17 @@
     private final TypeMirror[] primitiveTypeMirrors;
     private final TypeMirror[] boxedTypeMirrors;
 
-    private final TypeMirror nodeType;
     private final TypeMirror genericType;
 
     private final TypeData voidType;
 
-    private List<GuardData> guards;
-
 
     public TypeSystemData(TypeElement templateType, AnnotationMirror annotation,
-                    TypeData[] types, TypeMirror nodeType, TypeMirror genericType, TypeData voidType) {
+                    TypeData[] types, TypeMirror genericType, TypeData voidType) {
         super(templateType, annotation);
-        this.voidType = voidType;
         this.types = types;
-        this.nodeType = nodeType;
         this.genericType = genericType;
-
+        this.voidType = voidType;
         this.primitiveTypeMirrors = new TypeMirror[types.length];
         for (int i = 0; i < types.length; i++) {
             primitiveTypeMirrors[i] = types[i].getPrimitiveType();
@@ -70,16 +65,12 @@
         }
     }
 
-    public TypeData getVoidType() {
-        return voidType;
+    public boolean isGeneric(TypeMirror type) {
+        return Utils.typeEquals(getGenericType(), type);
     }
 
-    void setGuards(List<GuardData> guards) {
-        this.guards = guards;
-    }
-
-    public List<GuardData> getGuards() {
-        return guards;
+    public TypeData getVoidType() {
+        return voidType;
     }
 
     public TypeData[] getTypes() {
@@ -94,10 +85,6 @@
         return boxedTypeMirrors;
     }
 
-    public TypeMirror getNodeType() {
-        return nodeType;
-    }
-
     public TypeMirror getGenericType() {
         return genericType;
     }
@@ -116,6 +103,18 @@
         }
         return null;
     }
+    public TypeData findTypeData(TypeMirror type) {
+        if (Utils.typeEquals(voidType.getPrimitiveType(), type)) {
+            return voidType;
+        }
+
+        int index = findType(type);
+        if (index == -1) {
+            return null;
+        }
+        return types[index];
+    }
+
 
     public int findType(TypeMirror type) {
         for (int i = 0; i < types.length; i++) {
@@ -126,4 +125,11 @@
         return -1;
     }
 
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[template = " + Utils.getSimpleName(getTemplateType()) + ", types = " + Arrays.toString(types) + "]";
+    }
+
+
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -29,17 +29,19 @@
 import com.oracle.truffle.codegen.processor.template.*;
 
 
-abstract class TypeSystemMethodParser<E extends TemplateMethod> extends TemplateMethodParser<E> {
-
-    private final TypeSystemData typeSystem;
+abstract class TypeSystemMethodParser<E extends TemplateMethod> extends TemplateMethodParser<TypeSystemData, E> {
 
     public TypeSystemMethodParser(ProcessorContext context, TypeSystemData typeSystem) {
-        super(context);
-        this.typeSystem = typeSystem;
+        super(context, typeSystem);
     }
 
     public TypeSystemData getTypeSystem() {
-        return typeSystem;
+        return template;
+    }
+
+    @Override
+    public final boolean isParsable(ExecutableElement method) {
+        return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
     }
 
     protected TypeData findTypeByMethodName(ExecutableElement method, AnnotationMirror annotationMirror, String prefix) {
@@ -51,7 +53,7 @@
             return null;
         }
         String typeName = methodName.substring(prefix.length(), methodName.length());
-        TypeData type = typeSystem.findType(typeName);
+        TypeData type = getTypeSystem().findType(typeName);
         if (type == null) {
             String annotationName = TypeSystem.class.getSimpleName();
             getContext().getLog().error(method, "Type '%s' is not declared in this @%s.", typeName, annotationName);
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java	Thu Jan 17 17:21:16 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java	Fri Jan 18 13:28:12 2013 +0100
@@ -33,7 +33,6 @@
 
 import com.oracle.truffle.api.codegen.*;
 import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.operation.*;
 import com.oracle.truffle.codegen.processor.template.*;
 
 public class TypeSystemParser extends TemplateParser<TypeSystemData> {
@@ -61,31 +60,25 @@
             return null;
         }
 
-        TypeMirror nodeType = Utils.getAnnotationValueType(templateTypeAnnotation, "nodeBaseClass");
         TypeMirror genericType = context.getType(Object.class);
+        TypeData voidType = new TypeData(templateType, templateTypeAnnotation, context.getType(void.class), context.getType(Void.class));
 
-        TypeData voidType = null;
-        if (Utils.getAnnotationValueBoolean(templateTypeAnnotation, "hasVoid")) {
-            voidType = new TypeData(templateType, templateTypeAnnotation, context.getType(void.class), context.getType(Void.class));
-        }
+        TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation, types, genericType, voidType);
 
-        TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation, types, nodeType, genericType, voidType);
-
-        if (!verifyNodeBaseType(typeSystem)) {
+        if (!verifyExclusiveMethodAnnotation(templateType, TypeCast.class, TypeCheck.class)) {
             return null;
         }
 
-        if (!verifyExclusiveMethodAnnotation(templateType, TypeCast.class, TypeCheck.class, GuardCheck.class)) {
-            return null;
+        List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType));
+        typeSystem.setExtensionElements(getExtensionParser().parseAll(templateType, elements));
+        if (typeSystem.getExtensionElements() != null) {
+            elements.addAll(typeSystem.getExtensionElements());
         }
 
-        typeSystem.setExtensionElements(getExtensionParser().parseAll(templateType));
+        List<TypeCastData> casts = new TypeCastParser(context, typeSystem).parse(elements);
+        List<TypeCheckData> checks = new TypeCheckParser(context, typeSystem).parse(elements);
 
-        List<TypeCastData> casts = parseMethods(typeSystem, new TypeCastParser(context, typeSystem));
-        List<TypeCheckData> checks = parseMethods(typeSystem, new TypeCheckParser(context, typeSystem));
-        List<GuardData> guards = parseMethods(typeSystem, new GuardParser(context, typeSystem, typeSystem));
-
-        if (casts == null || checks == null || guards == null) {
+        if (casts == null || checks == null) {
             return null;
         }
 
@@ -97,8 +90,6 @@
             cast.getTargetType().addTypeCast(cast);
         }
 
-        typeSystem.setGuards(guards);
-
         if (!verifyGenericTypeChecksAndCasts(types)) {
             return null;
         }
@@ -155,43 +146,15 @@
         return valid;
     }
 
-    private boolean verifyNodeBaseType(TypeSystemData typeSystem) {
-        List<TypeData> types = new ArrayList<>(Arrays.asList(typeSystem.getTypes()));
-        if (typeSystem.getVoidType() != null) {
-            types.add(typeSystem.getVoidType());
-        }
-
-        TypeMirror[] args = new TypeMirror[]{context.getTruffleTypes().getFrame()};
-        List<String> missingMethods = new ArrayList<>();
-        for (TypeData typeData : types) {
-            String methodName = OperationCodeGenerator.executeMethodName(typeData);
-            ExecutableElement declared = Utils.getDeclaredMethodRecursive(Utils.fromTypeMirror(typeSystem.getNodeType()), methodName, args);
-            if (declared == null || declared.getModifiers().contains(Modifier.FINAL)) {
-                missingMethods.add(String.format("public %s %s(%s)",
-                                Utils.getSimpleName(typeData.getPrimitiveType()), methodName,
-                                Utils.getSimpleName(context.getTruffleTypes().getFrame())));
-            }
-        }
-
-        if (!missingMethods.isEmpty()) {
-            log.error(typeSystem.getTemplateType(), typeSystem.getTemplateTypeAnnotation(),
-                            Utils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "nodeBaseClass"),
-                            "The class '%s' does not declare the required non final method(s) %s.",
-                            Utils.getQualifiedName(typeSystem.getNodeType()), missingMethods);
-            return false;
-        }
-
-        return true;
-    }
 
     private TypeData[] parseTypes(TypeElement templateType, AnnotationMirror templateTypeAnnotation) {
-        List<TypeMirror> typeMirrors = Utils.getAnnotationValueList(templateTypeAnnotation, "types");
+        List<TypeMirror> typeMirrors = Utils.getAnnotationValueList(templateTypeAnnotation, "value");
         if (typeMirrors.size() == 0) {
-            log.error(templateType, templateTypeAnnotation, "At least one type child must be defined.");
+            log.error(templateType, templateTypeAnnotation, "At least one type must be defined.");
             return null;
         }
 
-        final AnnotationValue annotationValue = Utils.getAnnotationValue(templateTypeAnnotation, "types");
+        final AnnotationValue annotationValue = Utils.getAnnotationValue(templateTypeAnnotation, "value");
         final TypeMirror objectType = context.getType(Object.class);
 
         List<TypeData> types = new ArrayList<>();