changeset 16759:23415229349b

Truffle-DSL: new package structure.
author Christian Humer <christian.humer@gmail.com>
date Mon, 11 Aug 2014 15:57:14 +0200
parents c5f8eeb3cbc8
children 9f38d222fa6c
files graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationMirror.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationValue.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeCompilationUnit.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElementScanner.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeExecutableElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeImport.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeNames.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTree.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeBuilder.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeKind.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeMirror.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeVariableElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/GeneratedElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/GeneratedPackageElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/GeneratedTypeElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/GeneratedTypeMirror.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/FixWarningsVisitor.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/GenerateOverrideVisitor.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/AbstractCompiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/Compiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/CompilerFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JDTCompiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JavaCCompiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractClassElementFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractCodeElementFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractCompilationUnitFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/AbstractCompiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/Compiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/CompilerFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JavaCCompiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationMirror.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationValue.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeCompilationUnit.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElementScanner.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeExecutableElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeImport.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeNames.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTree.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeKind.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeMirror.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeVariableElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedPackageElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeMirror.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/AbstractCodeWriter.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/FixWarningsVisitor.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/GenerateOverrideVisitor.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/OrganizedImports.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CreateCastData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ImplicitCastData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeFieldData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ShortCircuitData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationThrowsData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Template.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCastData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCheckData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeExecutionData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeFieldData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGuardData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationThrowsData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/AbstractParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GenericParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ImplicitCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeExecutionData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ShortCircuitParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCheckParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ClassElementFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CodeElementFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CompilationUnitFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/Template.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardExpression.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java
diffstat 148 files changed, 16072 insertions(+), 16747 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-import javax.tools.Diagnostic.Kind;
-
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.template.MessageContainer.*;
-
-/**
- * THIS IS NOT PUBLIC API.
- */
-public abstract class AbstractParser<M extends Template> {
-
-    protected final ProcessorContext context;
-    protected final ProcessingEnvironment processingEnv;
-    protected RoundEnvironment roundEnv;
-
-    protected final Log log;
-
-    public AbstractParser() {
-        this.context = ProcessorContext.getInstance();
-        this.processingEnv = context.getEnvironment();
-        this.log = context.getLog();
-    }
-
-    public final M parse(RoundEnvironment env, Element element) {
-        this.roundEnv = env;
-        M model = null;
-        try {
-            AnnotationMirror mirror = null;
-            if (getAnnotationType() != null) {
-                mirror = Utils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType());
-            }
-
-            if (!context.getTruffleTypes().verify(context, element, mirror)) {
-                return null;
-            }
-            model = parse(element, mirror);
-            if (model == null) {
-                return null;
-            }
-
-            redirectMessages(new HashSet<MessageContainer>(), model, model);
-            model.emitMessages(context, log);
-            return filterErrorElements(model);
-        } catch (CompileErrorException e) {
-            log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage());
-            return null;
-        } finally {
-            this.roundEnv = null;
-        }
-    }
-
-    private void redirectMessages(Set<MessageContainer> visitedSinks, MessageContainer model, MessageContainer baseContainer) {
-        List<Message> messages = model.getMessages();
-        for (int i = messages.size() - 1; i >= 0; i--) {
-            Message message = messages.get(i);
-            if (!Utils.isEnclosedIn(baseContainer.getMessageElement(), message.getOriginalContainer().getMessageElement())) {
-                // redirect message
-                MessageContainer original = message.getOriginalContainer();
-                String text = wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText());
-                Message redirectedMessage = new Message(null, baseContainer, text, message.getKind());
-                model.getMessages().remove(i);
-                baseContainer.getMessages().add(redirectedMessage);
-            }
-        }
-
-        for (MessageContainer childContainer : model) {
-            if (visitedSinks.contains(childContainer)) {
-                continue;
-            }
-            visitedSinks.add(childContainer);
-
-            MessageContainer newBase = baseContainer;
-            if (childContainer.getBaseContainer() != null) {
-                newBase = childContainer.getBaseContainer();
-            }
-            redirectMessages(visitedSinks, childContainer, newBase);
-        }
-    }
-
-    private static String wrapText(Element element, AnnotationMirror mirror, String text) {
-        StringBuilder b = new StringBuilder();
-        if (element != null) {
-            b.append("Element " + element.toString());
-        }
-        if (mirror != null) {
-            b.append(" at annotation @" + Utils.getSimpleName(mirror.getAnnotationType()));
-        }
-
-        if (b.length() > 0) {
-            b.append(" is erroneous: ").append(text);
-            return b.toString();
-        } else {
-            return text;
-        }
-    }
-
-    protected M filterErrorElements(M model) {
-        return model.hasErrors() ? null : model;
-    }
-
-    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.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java	Mon Aug 11 15:57:14 2014 +0200
@@ -30,11 +30,13 @@
 import javax.lang.model.type.*;
 import javax.tools.*;
 
-import com.oracle.truffle.dsl.processor.ast.*;
-import com.oracle.truffle.dsl.processor.codewriter.*;
-import com.oracle.truffle.dsl.processor.compiler.*;
-import com.oracle.truffle.dsl.processor.node.*;
-import com.oracle.truffle.dsl.processor.template.*;
+import com.oracle.truffle.dsl.processor.generator.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.compiler.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.java.transform.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.parser.*;
 
 /**
  * THIS IS NOT PUBLIC API.
@@ -42,11 +44,11 @@
 class AnnotationProcessor<M extends Template> {
 
     private final AbstractParser<M> parser;
-    private final CompilationUnitFactory<M> factory;
+    private final AbstractCompilationUnitFactory<M> factory;
 
     private final Set<String> processedElements = new HashSet<>();
 
-    public AnnotationProcessor(AbstractParser<M> parser, CompilationUnitFactory<M> factory) {
+    public AnnotationProcessor(AbstractParser<M> parser, AbstractCompilationUnitFactory<M> factory) {
         this.parser = parser;
         this.factory = factory;
     }
@@ -56,11 +58,11 @@
     }
 
     @SuppressWarnings({"unchecked"})
-    public void process(RoundEnvironment env, Element element, boolean callback) {
+    public void process(Element element, boolean callback) {
         // since it is not guaranteed to be called only once by the compiler
         // we check for already processed elements to avoid errors when writing files.
         if (!callback && element instanceof TypeElement) {
-            String qualifiedName = Utils.getQualifiedName((TypeElement) element);
+            String qualifiedName = ElementUtils.getQualifiedName((TypeElement) element);
             if (processedElements.contains(qualifiedName)) {
                 return;
             }
@@ -75,12 +77,11 @@
 
         if (firstRun || !callback) {
             context.registerTemplate(type, null);
-            model = parser.parse(env, element);
+            model = parser.parse(element);
             context.registerTemplate(type, model);
 
             if (model != null) {
                 CodeCompilationUnit unit = factory.process(null, model);
-                patchGeneratedTypes(unit);
                 unit.setGeneratorAnnotationMirror(model.getTemplateTypeAnnotation());
                 unit.setGeneratorElement(model.getTemplateType());
 
@@ -96,55 +97,6 @@
         }
     }
 
-    private static void patchGeneratedTypes(CodeCompilationUnit unit) {
-        final Map<String, CodeTypeElement> classes = new HashMap<>();
-
-        unit.accept(new CodeElementScanner<Void, Void>() {
-            @Override
-            public Void visitType(CodeTypeElement e, Void p) {
-                classes.put(e.getSimpleName().toString(), e);
-                return super.visitType(e, p);
-            }
-
-        }, null);
-
-        unit.accept(new CodeElementScanner<Void, Void>() {
-            @Override
-            public Void visitExecutable(CodeExecutableElement e, Void p) {
-                if (e.getReturnType() instanceof GeneratedTypeMirror) {
-                    e.setReturnType(patchType(e.getReturnType()));
-                }
-                for (VariableElement element : e.getParameters()) {
-                    if (element instanceof CodeVariableElement) {
-                        CodeVariableElement var = ((CodeVariableElement) element);
-                        if (var.getType() instanceof GeneratedTypeMirror) {
-                            var.setType(patchType(var.getType()));
-                        }
-                    }
-                }
-                return super.visitExecutable(e, p);
-            }
-
-            @Override
-            public void visitTree(CodeTree e, Void p) {
-                if (e.getType() instanceof GeneratedTypeMirror) {
-                    e.setType(patchType(e.asType()));
-                }
-            }
-
-            private TypeMirror patchType(TypeMirror typeMirror) {
-                assert typeMirror instanceof GeneratedTypeMirror;
-                GeneratedTypeMirror type = (GeneratedTypeMirror) typeMirror;
-                CodeTypeElement generatedType = classes.get(Utils.fromTypeMirror(type).getSimpleName().toString());
-                if (generatedType == null) {
-                    return type;
-                }
-                return generatedType.asType();
-            }
-        }, null);
-
-    }
-
     private static class CodeWriter extends AbstractCodeWriter {
 
         private final Element originalElement;
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java	Mon Aug 11 15:57:14 2014 +0200
@@ -26,7 +26,7 @@
 import javax.lang.model.element.*;
 import javax.tools.Diagnostic.Kind;
 
-import com.oracle.truffle.dsl.processor.ast.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
 
 /**
  * THIS IS NOT PUBLIC API.
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java	Mon Aug 11 15:57:14 2014 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.dsl.processor;
 
-import static com.oracle.truffle.dsl.processor.Utils.*;
-
 import java.util.*;
 
 import javax.annotation.processing.*;
@@ -31,9 +29,9 @@
 import javax.lang.model.type.*;
 import javax.lang.model.util.*;
 
-import com.oracle.truffle.dsl.processor.ast.*;
-import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.ArrayCodeTypeMirror;
-import com.oracle.truffle.dsl.processor.template.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.model.*;
 
 /**
  * THIS IS NOT PUBLIC API.
@@ -43,13 +41,12 @@
     private final ProcessingEnvironment environment;
 
     private final Map<String, Template> models = new HashMap<>();
-    private final Map<String, Map<String, TypeMirror>> generatedClasses = new HashMap<>();
 
     private final ProcessCallback callback;
     private final Log log;
     private final TruffleTypes truffleTypes;
 
-    public ProcessorContext(ProcessingEnvironment env, ProcessCallback callback) {
+    ProcessorContext(ProcessingEnvironment env, ProcessCallback callback) {
         this.environment = env;
         this.callback = callback;
         this.log = new Log(environment);
@@ -69,86 +66,23 @@
     }
 
     public boolean containsTemplate(TypeElement element) {
-        return models.containsKey(Utils.getQualifiedName(element));
+        return models.containsKey(ElementUtils.getQualifiedName(element));
     }
 
     public void registerTemplate(TypeElement element, Template model) {
-        models.put(Utils.getQualifiedName(element), model);
-    }
-
-    public void registerType(TypeElement templateType, TypeMirror generatedTypeMirror) {
-        String templateQualifiedName = getQualifiedName(templateType);
-        Map<String, TypeMirror> simpleNameToType = generatedClasses.get(templateQualifiedName);
-        if (simpleNameToType == null) {
-            simpleNameToType = new HashMap<>();
-            generatedClasses.put(templateQualifiedName, simpleNameToType);
-        }
-        String generatedSimpleName = getSimpleName(generatedTypeMirror);
-        simpleNameToType.put(generatedSimpleName, generatedTypeMirror);
+        models.put(ElementUtils.getQualifiedName(element), model);
     }
 
     public Template getTemplate(TypeMirror templateTypeMirror, boolean invokeCallback) {
-        String qualifiedName = Utils.getQualifiedName(templateTypeMirror);
+        String qualifiedName = ElementUtils.getQualifiedName(templateTypeMirror);
         Template model = models.get(qualifiedName);
         if (model == null && invokeCallback) {
-            callback.callback(Utils.fromTypeMirror(templateTypeMirror));
+            callback.callback(ElementUtils.fromTypeMirror(templateTypeMirror));
             model = models.get(qualifiedName);
         }
         return model;
     }
 
-    public TypeMirror resolveNotYetCompiledType(TypeMirror mirror, Template templateHint) {
-        TypeMirror resolvedType = null;
-        if (mirror.getKind() == TypeKind.ARRAY) {
-            TypeMirror originalComponentType = ((ArrayType) mirror).getComponentType();
-            TypeMirror resolvedComponent = resolveNotYetCompiledType(originalComponentType, templateHint);
-            if (resolvedComponent != originalComponentType) {
-                return new ArrayCodeTypeMirror(resolvedComponent);
-            }
-        }
-
-        if (mirror.getKind() == TypeKind.ERROR) {
-            Element element = ((ErrorType) mirror).asElement();
-            ElementKind kind = element.getKind();
-            if (kind == ElementKind.CLASS || kind == ElementKind.PARAMETER || kind == ElementKind.ENUM) {
-                String simpleName = element.getSimpleName().toString();
-                resolvedType = findGeneratedClassBySimpleName(simpleName, templateHint);
-            }
-        } else {
-            resolvedType = mirror;
-        }
-
-        return resolvedType;
-    }
-
-    public TypeMirror findGeneratedClassBySimpleName(String simpleName, Template templateHint) {
-        if (templateHint == null) {
-            // search all
-            for (String qualifiedTemplateName : generatedClasses.keySet()) {
-                Map<String, TypeMirror> mirrors = generatedClasses.get(qualifiedTemplateName);
-                if (mirrors.get(simpleName) != null) {
-                    return mirrors.get(simpleName);
-                }
-            }
-            return null;
-        } else {
-            String templateQualifiedName = getQualifiedName(templateHint.getTemplateType());
-            Map<String, TypeMirror> simpleNameToType = generatedClasses.get(templateQualifiedName);
-            if (simpleNameToType == null) {
-                return null;
-            }
-            return simpleNameToType.get(simpleName);
-        }
-    }
-
-    public TypeMirror getType(String className) {
-        TypeElement element = environment.getElementUtils().getTypeElement(className);
-        if (element != null) {
-            return element.asType();
-        }
-        return null;
-    }
-
     public TypeMirror getType(Class<?> element) {
         TypeMirror mirror;
         if (element.isPrimitive()) {
@@ -191,6 +125,14 @@
         return getType(type.getQualifiedName().toString());
     }
 
+    private TypeMirror getType(String className) {
+        TypeElement element = environment.getElementUtils().getTypeElement(className);
+        if (element != null) {
+            return element.asType();
+        }
+        return null;
+    }
+
     public TypeMirror reloadType(TypeMirror type) {
         if (type instanceof CodeTypeMirror) {
             return type;
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java	Mon Aug 11 15:57:14 2014 +0200
@@ -31,8 +31,9 @@
 import javax.tools.Diagnostic.Kind;
 
 import com.oracle.truffle.dsl.processor.ProcessorContext.ProcessCallback;
-import com.oracle.truffle.dsl.processor.node.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
+import com.oracle.truffle.dsl.processor.generator.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.parser.*;
 
 /**
  * THIS IS NOT PUBLIC API.
@@ -44,8 +45,6 @@
 
     private List<AnnotationProcessor<?>> generators;
 
-    private RoundEnvironment round;
-
     @Override
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
         if (!roundEnv.processingOver()) {
@@ -55,7 +54,6 @@
     }
 
     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 {
@@ -64,7 +62,7 @@
                 AbstractParser<?> parser = generator.getParser();
                 if (parser.getAnnotationType() != null) {
                     for (Element e : env.getElementsAnnotatedWith(parser.getAnnotationType())) {
-                        processElement(env, generator, e, false);
+                        processElement(generator, e, false);
                     }
                 }
 
@@ -72,24 +70,23 @@
                     for (Element e : env.getElementsAnnotatedWith(annotationType)) {
                         TypeElement processedType;
                         if (parser.isDelegateToRootDeclaredType()) {
-                            processedType = Utils.findRootEnclosingType(e);
+                            processedType = ElementUtils.findRootEnclosingType(e);
                         } else {
-                            processedType = Utils.findNearestEnclosingType(e);
+                            processedType = ElementUtils.findNearestEnclosingType(e);
                         }
-                        processElement(env, generator, processedType, false);
+                        processElement(generator, processedType, false);
                     }
                 }
 
             }
         } finally {
             ProcessorContext.setThreadLocalInstance(null);
-            this.round = null;
         }
     }
 
-    private static void processElement(RoundEnvironment env, AnnotationProcessor<?> generator, Element e, boolean callback) {
+    private static void processElement(AnnotationProcessor<?> generator, Element e, boolean callback) {
         try {
-            generator.process(env, e, callback);
+            generator.process(e, callback);
         } catch (Throwable e1) {
             handleThrowable(generator, e1, e);
         }
@@ -97,7 +94,7 @@
 
     private static void handleThrowable(AnnotationProcessor<?> generator, Throwable t, Element e) {
         String message = "Uncaught error in " + generator.getClass().getSimpleName() + " while processing " + e;
-        ProcessorContext.getInstance().getEnvironment().getMessager().printMessage(Kind.ERROR, message + ": " + Utils.printException(t), e);
+        ProcessorContext.getInstance().getEnvironment().getMessager().printMessage(Kind.ERROR, message + ": " + ElementUtils.printException(t), e);
     }
 
     @Override
@@ -107,7 +104,7 @@
             if (annotationType != null) {
                 Annotation annotation = template.getAnnotation(annotationType);
                 if (annotation != null) {
-                    processElement(round, generator, template, true);
+                    processElement(generator, template, true);
                 }
             }
         }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Mon Aug 11 15:57:14 2014 +0200
@@ -73,7 +73,7 @@
 
     private final List<String> errors = new ArrayList<>();
 
-    public TruffleTypes(ProcessorContext context) {
+    TruffleTypes(ProcessorContext context) {
         node = getRequired(context, Node.class);
         nodeArray = context.getEnvironment().getTypeUtils().getArrayType(node);
         unexpectedValueException = getRequired(context, UnexpectedResultException.class);
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1012 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor;
-
-import java.io.*;
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.ast.*;
-import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.DeclaredCodeTypeMirror;
-import com.oracle.truffle.dsl.processor.compiler.*;
-
-/**
- * THIS IS NOT PUBLIC API.
- */
-public class Utils {
-
-    public static ExecutableElement findExecutableElement(DeclaredType type, String name) {
-        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements());
-        for (ExecutableElement executableElement : elements) {
-            if (executableElement.getSimpleName().toString().equals(name)) {
-                return executableElement;
-            }
-        }
-        return null;
-    }
-
-    public static boolean needsCastTo(TypeMirror sourceType, TypeMirror targetType) {
-        if (typeEquals(sourceType, targetType)) {
-            return false;
-        } else if (isObject(targetType)) {
-            return false;
-        } else if (isVoid(targetType)) {
-            return false;
-        } else if (isAssignable(sourceType, targetType)) {
-            return false;
-        }
-        return true;
-    }
-
-    public static VariableElement findVariableElement(DeclaredType type, String name) {
-        List<? extends VariableElement> elements = ElementFilter.fieldsIn(type.asElement().getEnclosedElements());
-        for (VariableElement variableElement : elements) {
-            if (variableElement.getSimpleName().toString().equals(name)) {
-                return variableElement;
-            }
-        }
-        return null;
-    }
-
-    public static String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
-        if (method instanceof CodeExecutableElement) {
-            return ((CodeExecutableElement) method).getBody();
-        } else {
-            return CompilerFactory.getCompiler(method).getMethodBody(env, method);
-        }
-    }
-
-    public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) {
-        TypeMirror boxedType = primitiveType;
-        if (boxedType.getKind().isPrimitive()) {
-            boxedType = context.getEnvironment().getTypeUtils().boxedClass((PrimitiveType) boxedType).asType();
-        }
-        return boxedType;
-    }
-
-    public static List<TypeMirror> asTypeMirrors(List<? extends Element> elements) {
-        List<TypeMirror> types = new ArrayList<>(elements.size());
-        for (Element element : elements) {
-            types.add(element.asType());
-        }
-        return types;
-    }
-
-    public static DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) {
-        return new DeclaredCodeTypeMirror(typeElem, Arrays.asList(typeArgs));
-    }
-
-    public static List<AnnotationMirror> collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element,
-                    Class<? extends Annotation> annotationClass) {
-        List<AnnotationMirror> result = new ArrayList<>();
-        if (markerAnnotation != null) {
-            result.addAll(Utils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName));
-        }
-        AnnotationMirror explicit = Utils.findAnnotationMirror(context.getEnvironment(), element, annotationClass);
-        if (explicit != null) {
-            result.add(explicit);
-        }
-        return result;
-    }
-
-    public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror[] types) {
-        if (types.length == 0) {
-            return context.getType(Object.class);
-        }
-        TypeMirror prev = types[0];
-        for (int i = 1; i < types.length; i++) {
-            prev = getCommonSuperType(context, prev, types[i]);
-        }
-        return prev;
-    }
-
-    private static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror type1, TypeMirror type2) {
-        if (typeEquals(type1, type2)) {
-            return type1;
-        }
-        TypeElement element1 = fromTypeMirror(type1);
-        TypeElement element2 = fromTypeMirror(type2);
-        if (element1 == null || element2 == null) {
-            return context.getType(Object.class);
-        }
-
-        List<TypeElement> element1Types = getDirectSuperTypes(element1);
-        element1Types.add(0, element1);
-        List<TypeElement> element2Types = getDirectSuperTypes(element2);
-        element2Types.add(0, element2);
-
-        for (TypeElement superType1 : element1Types) {
-            for (TypeElement superType2 : element2Types) {
-                if (typeEquals(superType1.asType(), superType2.asType())) {
-                    return superType2.asType();
-                }
-            }
-        }
-        return context.getType(Object.class);
-    }
-
-    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:
-            case BYTE:
-            case CHAR:
-            case DOUBLE:
-            case FLOAT:
-            case INT:
-            case SHORT:
-            case LONG:
-            case DECLARED:
-            case VOID:
-            case TYPEVAR:
-                return false;
-            case ARRAY:
-                return hasError(((ArrayType) mirror).getComponentType());
-            case ERROR:
-                return true;
-            default:
-                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
-        }
-    }
-
-    public static boolean isSubtype(TypeMirror type1, TypeMirror type2) {
-        if (type1 instanceof CodeTypeMirror && type2 instanceof CodeTypeMirror) {
-            throw new UnsupportedOperationException();
-        }
-        return ProcessorContext.getInstance().getEnvironment().getTypeUtils().isSubtype(type1, type2);
-    }
-
-    public static boolean isAssignable(TypeMirror from, TypeMirror to) {
-        ProcessorContext context = ProcessorContext.getInstance();
-
-        if (!(from instanceof CodeTypeMirror) && !(to instanceof CodeTypeMirror)) {
-            return context.getEnvironment().getTypeUtils().isAssignable(context.reloadType(from), context.reloadType(to));
-        } else {
-            return isAssignableImpl(from, to);
-        }
-    }
-
-    private static boolean isAssignableImpl(TypeMirror from, TypeMirror to) {
-        // JLS 5.1.1 identity conversion
-        if (Utils.typeEquals(from, to)) {
-            return true;
-        }
-
-        if (isObject(to)) {
-            return true;
-        }
-
-        // JLS 5.1.2 widening primitives
-        if (Utils.isPrimitive(from) && Utils.isPrimitive(to)) {
-            TypeKind fromKind = from.getKind();
-            TypeKind toKind = to.getKind();
-            switch (fromKind) {
-                case BYTE:
-                    switch (toKind) {
-                        case SHORT:
-                        case INT:
-                        case LONG:
-                        case FLOAT:
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-                case SHORT:
-                    switch (toKind) {
-                        case INT:
-                        case LONG:
-                        case FLOAT:
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-                case CHAR:
-                    switch (toKind) {
-                        case INT:
-                        case LONG:
-                        case FLOAT:
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-                case INT:
-                    switch (toKind) {
-                        case LONG:
-                        case FLOAT:
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-                case LONG:
-                    switch (toKind) {
-                        case FLOAT:
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-                case FLOAT:
-                    switch (toKind) {
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-
-            }
-            return false;
-        } else if (Utils.isPrimitive(from) || Utils.isPrimitive(to)) {
-            return false;
-        }
-
-        if (from instanceof ArrayType && to instanceof ArrayType) {
-            return isAssignable(((ArrayType) from).getComponentType(), ((ArrayType) to).getComponentType());
-        }
-
-        if (from instanceof ArrayType || to instanceof ArrayType) {
-            return false;
-        }
-
-        TypeElement fromType = Utils.fromTypeMirror(from);
-        TypeElement toType = Utils.fromTypeMirror(to);
-        if (fromType == null || toType == null) {
-            return false;
-        }
-        // JLS 5.1.6 narrowing reference conversion
-
-        List<TypeElement> superTypes = Utils.getSuperTypes(fromType);
-        for (TypeElement superType : superTypes) {
-            if (Utils.typeEquals(superType.asType(), to)) {
-                return true;
-            }
-        }
-
-        // TODO more spec
-        return false;
-    }
-
-    public static Set<Modifier> modifiers(Modifier... modifier) {
-        return new LinkedHashSet<>(Arrays.asList(modifier));
-    }
-
-    public static String getTypeId(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case BOOLEAN:
-                return "Boolean";
-            case BYTE:
-                return "Byte";
-            case CHAR:
-                return "Char";
-            case DOUBLE:
-                return "Double";
-            case FLOAT:
-                return "Float";
-            case SHORT:
-                return "Short";
-            case INT:
-                return "Int";
-            case LONG:
-                return "Long";
-            case DECLARED:
-                return fixECJBinaryNameIssue(((DeclaredType) mirror).asElement().getSimpleName().toString());
-            case ARRAY:
-                return getTypeId(((ArrayType) mirror).getComponentType()) + "Array";
-            case VOID:
-                return "Void";
-            case WILDCARD:
-                StringBuilder b = new StringBuilder();
-                WildcardType type = (WildcardType) mirror;
-                if (type.getExtendsBound() != null) {
-                    b.append("Extends").append(getTypeId(type.getExtendsBound()));
-                } else if (type.getSuperBound() != null) {
-                    b.append("Super").append(getTypeId(type.getExtendsBound()));
-                }
-                return b.toString();
-            case TYPEVAR:
-                return "Any";
-            case ERROR:
-                throw new CompileErrorException("Type error " + mirror);
-            default:
-                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
-        }
-    }
-
-    public static String getSimpleName(TypeElement element) {
-        return getSimpleName(element.asType());
-    }
-
-    public static String getSimpleName(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case BOOLEAN:
-                return "boolean";
-            case BYTE:
-                return "byte";
-            case CHAR:
-                return "char";
-            case DOUBLE:
-                return "double";
-            case FLOAT:
-                return "float";
-            case SHORT:
-                return "short";
-            case INT:
-                return "int";
-            case LONG:
-                return "long";
-            case DECLARED:
-                return getDeclaredName((DeclaredType) mirror);
-            case ARRAY:
-                return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]";
-            case VOID:
-                return "void";
-            case WILDCARD:
-                return getWildcardName((WildcardType) mirror);
-            case TYPEVAR:
-                return "?";
-            case ERROR:
-                throw new CompileErrorException("Type error " + mirror);
-            default:
-                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
-        }
-    }
-
-    private static String getWildcardName(WildcardType type) {
-        StringBuilder b = new StringBuilder();
-        if (type.getExtendsBound() != null) {
-            b.append("? extends ").append(getSimpleName(type.getExtendsBound()));
-        } else if (type.getSuperBound() != null) {
-            b.append("? super ").append(getSimpleName(type.getExtendsBound()));
-        }
-        return b.toString();
-    }
-
-    private static String getDeclaredName(DeclaredType element) {
-        String simpleName = fixECJBinaryNameIssue(element.asElement().getSimpleName().toString());
-
-        if (element.getTypeArguments().size() == 0) {
-            return simpleName;
-        }
-
-        StringBuilder b = new StringBuilder(simpleName);
-        b.append("<");
-        if (element.getTypeArguments().size() > 0) {
-            for (int i = 0; i < element.getTypeArguments().size(); i++) {
-                b.append(getSimpleName(element.getTypeArguments().get(i)));
-                if (i < element.getTypeArguments().size() - 1) {
-                    b.append(", ");
-                }
-            }
-        }
-        b.append(">");
-        return b.toString();
-    }
-
-    public static String fixECJBinaryNameIssue(String name) {
-        if (name.contains("$")) {
-            int lastIndex = name.lastIndexOf('$');
-            return name.substring(lastIndex + 1, name.length());
-        }
-        return name;
-    }
-
-    public static String getQualifiedName(TypeElement element) {
-        String qualifiedName = element.getQualifiedName().toString();
-        if (qualifiedName.contains("$")) {
-            /*
-             * If a class gets loaded in its binary form by the ECJ compiler it fails to produce the
-             * proper canonical class name. It leaves the $ in the qualified name of the class. So
-             * one instance of a TypeElement may be loaded in binary and one in source form. The
-             * current type comparison in #typeEquals compares by the qualified name so the
-             * qualified name must match. This is basically a hack to fix the returned qualified
-             * name of eclipse.
-             */
-            qualifiedName = qualifiedName.replace('$', '.');
-        }
-        return qualifiedName;
-    }
-
-    public static String getQualifiedName(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case BOOLEAN:
-                return "boolean";
-            case BYTE:
-                return "byte";
-            case CHAR:
-                return "char";
-            case DOUBLE:
-                return "double";
-            case SHORT:
-                return "short";
-            case FLOAT:
-                return "float";
-            case INT:
-                return "int";
-            case LONG:
-                return "long";
-            case DECLARED:
-                return getQualifiedName(fromTypeMirror(mirror));
-            case ARRAY:
-                return getQualifiedName(((ArrayType) mirror).getComponentType());
-            case VOID:
-                return "void";
-            case TYPEVAR:
-                return getSimpleName(mirror);
-            case ERROR:
-                throw new CompileErrorException("Type error " + mirror);
-            case EXECUTABLE:
-                return ((ExecutableType) mirror).toString();
-            case NONE:
-                return "$none";
-            default:
-                throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror);
-        }
-    }
-
-    public static boolean isVoid(TypeMirror mirror) {
-        return mirror != null && mirror.getKind() == TypeKind.VOID;
-    }
-
-    public static boolean isPrimitive(TypeMirror mirror) {
-        return mirror != null && mirror.getKind().isPrimitive();
-    }
-
-    public static boolean isPrimitiveOrVoid(TypeMirror mirror) {
-        return isPrimitive(mirror) || isVoid(mirror);
-    }
-
-    public static List<String> getQualifiedSuperTypeNames(TypeElement element) {
-        List<TypeElement> types = getSuperTypes(element);
-        List<String> qualifiedNames = new ArrayList<>();
-        for (TypeElement type : types) {
-            qualifiedNames.add(getQualifiedName(type));
-        }
-        return qualifiedNames;
-    }
-
-    public static List<TypeElement> getDeclaredTypes(TypeElement element) {
-        return ElementFilter.typesIn(element.getEnclosedElements());
-    }
-
-    public static VariableElement findDeclaredField(TypeMirror type, String singletonName) {
-        List<VariableElement> elements = ElementFilter.fieldsIn(fromTypeMirror(type).getEnclosedElements());
-        for (VariableElement var : elements) {
-            if (var.getSimpleName().toString().equals(singletonName)) {
-                return var;
-            }
-        }
-        return null;
-    }
-
-    public static boolean isEnclosedIn(Element enclosedIn, Element element) {
-        if (element == null) {
-            return false;
-        } else if (enclosedIn.equals(element)) {
-            return true;
-        } else {
-            return isEnclosedIn(enclosedIn, 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 null;
-    }
-
-    public 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> getDirectSuperTypes(TypeElement element) {
-        List<TypeElement> types = new ArrayList<>();
-        if (element.getSuperclass() != null) {
-            TypeElement superElement = fromTypeMirror(element.getSuperclass());
-            if (superElement != null) {
-                types.add(superElement);
-                types.addAll(getDirectSuperTypes(superElement));
-            }
-        }
-
-        return types;
-    }
-
-    public static List<TypeMirror> getAssignableTypes(ProcessorContext context, TypeMirror type) {
-        if (isPrimitive(type)) {
-            return Arrays.asList(type, boxType(context, type), context.getType(Object.class));
-        } else if (type.getKind() == TypeKind.ARRAY) {
-            return Arrays.asList(type, context.getType(Object.class));
-        } else if (type.getKind() == TypeKind.DECLARED) {
-            List<TypeElement> types = getSuperTypes(fromTypeMirror(type));
-            List<TypeMirror> mirrors = new ArrayList<>(types.size());
-            mirrors.add(type);
-            for (TypeElement typeElement : types) {
-                mirrors.add(typeElement.asType());
-            }
-            return mirrors;
-        } else {
-            return Collections.emptyList();
-        }
-    }
-
-    public static List<TypeElement> getSuperTypes(TypeElement element) {
-        List<TypeElement> types = new ArrayList<>();
-        List<TypeElement> superTypes = null;
-        List<TypeElement> superInterfaces = null;
-        if (element.getSuperclass() != null) {
-            TypeElement superElement = fromTypeMirror(element.getSuperclass());
-            if (superElement != null) {
-                types.add(superElement);
-                superTypes = getSuperTypes(superElement);
-            }
-        }
-        for (TypeMirror interfaceMirror : element.getInterfaces()) {
-            TypeElement interfaceElement = fromTypeMirror(interfaceMirror);
-            if (interfaceElement != null) {
-                types.add(interfaceElement);
-                superInterfaces = getSuperTypes(interfaceElement);
-            }
-        }
-
-        if (superTypes != null) {
-            types.addAll(superTypes);
-        }
-
-        if (superInterfaces != null) {
-            types.addAll(superInterfaces);
-        }
-
-        return types;
-    }
-
-    public static String getPackageName(TypeElement element) {
-        return findPackageElement(element).getQualifiedName().toString();
-    }
-
-    public static String getPackageName(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case BOOLEAN:
-            case BYTE:
-            case CHAR:
-            case DOUBLE:
-            case FLOAT:
-            case SHORT:
-            case INT:
-            case LONG:
-            case VOID:
-            case TYPEVAR:
-                return null;
-            case DECLARED:
-                PackageElement pack = findPackageElement(fromTypeMirror(mirror));
-                if (pack == null) {
-                    throw new IllegalArgumentException("No package element found for declared type " + getSimpleName(mirror));
-                }
-                return pack.getQualifiedName().toString();
-            case ARRAY:
-                return getSimpleName(((ArrayType) mirror).getComponentType());
-            default:
-                throw new RuntimeException("Unknown type specified " + mirror.getKind());
-        }
-    }
-
-    public static String createConstantName(String simpleName) {
-        // TODO use camel case to produce underscores.
-        return simpleName.toString().toUpperCase();
-    }
-
-    public static TypeElement fromTypeMirror(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case DECLARED:
-                return (TypeElement) ((DeclaredType) mirror).asElement();
-            case ARRAY:
-                return fromTypeMirror(((ArrayType) mirror).getComponentType());
-            default:
-                return null;
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public static <T> List<T> getAnnotationValueList(Class<T> expectedListType, AnnotationMirror mirror, String name) {
-        List<? extends AnnotationValue> values = getAnnotationValue(List.class, mirror, name);
-        List<T> result = new ArrayList<>();
-
-        if (values != null) {
-            for (AnnotationValue value : values) {
-                T annotationValue = resolveAnnotationValue(expectedListType, value);
-                if (annotationValue != null) {
-                    result.add(annotationValue);
-                }
-            }
-        }
-        return result;
-    }
-
-    public static <T> T getAnnotationValue(Class<T> expectedType, AnnotationMirror mirror, String name) {
-        return resolveAnnotationValue(expectedType, getAnnotationValue(mirror, name));
-    }
-
-    @SuppressWarnings({"unchecked"})
-    private static <T> T resolveAnnotationValue(Class<T> expectedType, AnnotationValue value) {
-        if (value == null) {
-            return null;
-        }
-
-        Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null);
-        if (unboxedValue != null) {
-            if (expectedType == TypeMirror.class && unboxedValue instanceof String) {
-                return null;
-            }
-            if (!expectedType.isAssignableFrom(unboxedValue.getClass())) {
-                throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName());
-            }
-        }
-        return (T) unboxedValue;
-    }
-
-    public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) {
-        ExecutableElement valueMethod = null;
-        for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) {
-            if (method.getSimpleName().toString().equals(name)) {
-                valueMethod = method;
-                break;
-            }
-        }
-
-        if (valueMethod == null) {
-            return null;
-        }
-
-        AnnotationValue value = mirror.getElementValues().get(valueMethod);
-        if (value == null) {
-            value = valueMethod.getDefaultValue();
-        }
-
-        return value;
-    }
-
-    private static class AnnotationValueVisitorImpl extends AbstractAnnotationValueVisitor7<Object, Void> {
-
-        @Override
-        public Object visitBoolean(boolean b, Void p) {
-            return Boolean.valueOf(b);
-        }
-
-        @Override
-        public Object visitByte(byte b, Void p) {
-            return Byte.valueOf(b);
-        }
-
-        @Override
-        public Object visitChar(char c, Void p) {
-            return c;
-        }
-
-        @Override
-        public Object visitDouble(double d, Void p) {
-            return d;
-        }
-
-        @Override
-        public Object visitFloat(float f, Void p) {
-            return f;
-        }
-
-        @Override
-        public Object visitInt(int i, Void p) {
-            return i;
-        }
-
-        @Override
-        public Object visitLong(long i, Void p) {
-            return i;
-        }
-
-        @Override
-        public Object visitShort(short s, Void p) {
-            return s;
-        }
-
-        @Override
-        public Object visitString(String s, Void p) {
-            return s;
-        }
-
-        @Override
-        public Object visitType(TypeMirror t, Void p) {
-            return t;
-        }
-
-        @Override
-        public Object visitEnumConstant(VariableElement c, Void p) {
-            return c;
-        }
-
-        @Override
-        public Object visitAnnotation(AnnotationMirror a, Void p) {
-            return a;
-        }
-
-        @Override
-        public Object visitArray(List<? extends AnnotationValue> vals, Void p) {
-            return vals;
-        }
-
-    }
-
-    public static String printException(Throwable e) {
-        StringWriter string = new StringWriter();
-        PrintWriter writer = new PrintWriter(string);
-        e.printStackTrace(writer);
-        writer.flush();
-        return e.getMessage() + "\r\n" + string.toString();
-    }
-
-    public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, Element element, Class<?> annotationClass) {
-        return findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), annotationClass);
-    }
-
-    public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List<? extends AnnotationMirror> mirrors, Class<?> annotationClass) {
-        TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName());
-        return findAnnotationMirror(mirrors, expectedAnnotationType);
-    }
-
-    public static AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> mirrors, TypeElement expectedAnnotationType) {
-        for (AnnotationMirror mirror : mirrors) {
-            DeclaredType annotationType = mirror.getAnnotationType();
-            TypeElement actualAnnotationType = (TypeElement) annotationType.asElement();
-            if (actualAnnotationType.equals(expectedAnnotationType)) {
-                return mirror;
-            }
-        }
-        return null;
-    }
-
-    private static PackageElement findPackageElement(Element type) {
-        List<Element> hierarchy = getElementHierarchy(type);
-        for (Element element : hierarchy) {
-            if (element.getKind() == ElementKind.PACKAGE) {
-                return (PackageElement) element;
-            }
-        }
-        return null;
-    }
-
-    public static String firstLetterUpperCase(String name) {
-        if (name == null || name.isEmpty()) {
-            return name;
-        }
-        return Character.toUpperCase(name.charAt(0)) + name.substring(1, name.length());
-    }
-
-    public static String firstLetterLowerCase(String name) {
-        if (name == null || name.isEmpty()) {
-            return name;
-        }
-        return Character.toLowerCase(name.charAt(0)) + name.substring(1, name.length());
-    }
-
-    private static ExecutableElement getDeclaredMethod(TypeElement element, String name, TypeMirror[] params) {
-        List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements());
-        method: for (ExecutableElement method : methods) {
-            if (!method.getSimpleName().toString().equals(name)) {
-                continue;
-            }
-            if (method.getParameters().size() != params.length) {
-                continue;
-            }
-            for (int i = 0; i < params.length; i++) {
-                TypeMirror param1 = params[i];
-                TypeMirror param2 = method.getParameters().get(i).asType();
-                if (param1.getKind() != TypeKind.TYPEVAR && param2.getKind() != TypeKind.TYPEVAR) {
-                    if (!getQualifiedName(param1).equals(getQualifiedName(param2))) {
-                        continue method;
-                    }
-                }
-            }
-            return method;
-        }
-        return null;
-    }
-
-    private static boolean isDeclaredMethod(TypeElement element, String name, TypeMirror[] params) {
-        return getDeclaredMethod(element, name, params) != null;
-    }
-
-    public static boolean isDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) {
-        List<TypeElement> superElements = getSuperTypes(element);
-
-        for (TypeElement typeElement : superElements) {
-            if (isDeclaredMethod(typeElement, name, params)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private static ExecutableElement getDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) {
-        List<TypeElement> superElements = getSuperTypes(element);
-
-        for (TypeElement typeElement : superElements) {
-            ExecutableElement declared = getDeclaredMethod(typeElement, name, params);
-            if (declared != null) {
-                return declared;
-            }
-        }
-        return null;
-    }
-
-    public static ExecutableElement getDeclaredMethodRecursive(TypeElement element, String name, TypeMirror[] params) {
-        ExecutableElement declared = getDeclaredMethod(element, name, params);
-        if (declared != null) {
-            return declared;
-        }
-        return getDeclaredMethodInSuperType(element, name, params);
-    }
-
-    public static boolean typeEquals(TypeMirror type1, TypeMirror type2) {
-        if (type1 == null && type2 == null) {
-            return true;
-        } else if (type1 == null || type2 == null) {
-            return false;
-        } else if (type1 == type2) {
-            return true;
-        }
-        String qualified1 = getQualifiedName(type1);
-        String qualified2 = getQualifiedName(type2);
-
-        if (type1.getKind() == TypeKind.ARRAY || type2.getKind() == TypeKind.ARRAY) {
-            if (type1.getKind() == TypeKind.ARRAY && type2.getKind() == TypeKind.ARRAY) {
-                return typeEquals(((ArrayType) type1).getComponentType(), ((ArrayType) type2).getComponentType());
-            } else {
-                return false;
-            }
-        }
-        return qualified1.equals(qualified2);
-    }
-
-    public static int compareByTypeHierarchy(TypeMirror t1, TypeMirror t2) {
-        if (typeEquals(t1, t2)) {
-            return 0;
-        }
-        Set<String> t1SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t1)));
-        if (t1SuperSet.contains(getQualifiedName(t2))) {
-            return -1;
-        }
-
-        Set<String> t2SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t2)));
-        if (t2SuperSet.contains(getQualifiedName(t1))) {
-            return 1;
-        }
-        return 0;
-    }
-
-    public static boolean canThrowType(List<? extends TypeMirror> thrownTypes, TypeMirror exceptionType) {
-        if (Utils.containsType(thrownTypes, exceptionType)) {
-            return true;
-        }
-
-        if (isRuntimeException(exceptionType)) {
-            return true;
-        }
-
-        // search for any super types
-        TypeElement exceptionTypeElement = fromTypeMirror(exceptionType);
-        List<TypeElement> superTypes = getSuperTypes(exceptionTypeElement);
-        for (TypeElement typeElement : superTypes) {
-            if (Utils.containsType(thrownTypes, typeElement.asType())) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public static Modifier getVisibility(Set<Modifier> modifier) {
-        for (Modifier mod : modifier) {
-            if (mod == Modifier.PUBLIC || mod == Modifier.PRIVATE || 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);
-        if (!typeSuperSet.contains(Throwable.class.getCanonicalName()) && !typeName.equals(Throwable.class.getCanonicalName())) {
-            throw new IllegalArgumentException("Given type does not extend Throwable.");
-        }
-        return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || typeName.equals(RuntimeException.class.getCanonicalName());
-    }
-
-    private static boolean containsType(Collection<? extends TypeMirror> collection, TypeMirror type) {
-        for (TypeMirror otherTypeMirror : collection) {
-            if (typeEquals(otherTypeMirror, type)) {
-                return true;
-            }
-        }
-        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;
-    }
-
-    public static boolean isObject(TypeMirror actualType) {
-        return actualType.getKind() == TypeKind.DECLARED && getQualifiedName(actualType).equals("java.lang.Object");
-    }
-
-    public static boolean isFieldAccessible(Element element, VariableElement variable) {
-        TypeElement type = Utils.findNearestEnclosingType(element);
-        TypeElement varType = Utils.findNearestEnclosingType(variable);
-
-        while (type != null) {
-            if (typeEquals(type.asType(), varType.asType())) {
-                return true;
-            }
-            if (type.getSuperclass() != null) {
-                type = Utils.fromTypeMirror(type.getSuperclass());
-            } else {
-                type = null;
-            }
-        }
-        return false;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationMirror.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-
-public class CodeAnnotationMirror implements AnnotationMirror {
-
-    private final DeclaredType annotationType;
-    private final Map<ExecutableElement, AnnotationValue> values = new LinkedHashMap<>();
-
-    public CodeAnnotationMirror(DeclaredType annotationType) {
-        this.annotationType = annotationType;
-    }
-
-    @Override
-    public DeclaredType getAnnotationType() {
-        return annotationType;
-    }
-
-    @Override
-    public Map<? extends ExecutableElement, ? extends AnnotationValue> getElementValues() {
-        return values;
-    }
-
-    public AnnotationValue getElementValue(ExecutableElement method) {
-        return values.get(method);
-    }
-
-    public void setElementValue(ExecutableElement method, AnnotationValue value) {
-        values.put(method, value);
-    }
-
-    public ExecutableElement findExecutableElement(String name) {
-        return Utils.findExecutableElement(annotationType, name);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationValue.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public class CodeAnnotationValue implements AnnotationValue {
-
-    private final Object value;
-
-    public CodeAnnotationValue(Object value) {
-        Objects.requireNonNull(value);
-        if ((value instanceof AnnotationMirror) || (value instanceof List<?>) || (value instanceof Boolean) || (value instanceof Byte) || (value instanceof Character) || (value instanceof Double) ||
-                        (value instanceof VariableElement) || (value instanceof Float) || (value instanceof Integer) || (value instanceof Long) || (value instanceof Short) ||
-                        (value instanceof String) || (value instanceof TypeMirror)) {
-            this.value = value;
-        } else {
-            throw new IllegalArgumentException("Invalid annotation value type " + value.getClass().getName());
-        }
-    }
-
-    @Override
-    public Object getValue() {
-        return value;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
-        if (value instanceof AnnotationMirror) {
-            return v.visitAnnotation((AnnotationMirror) value, p);
-        } else if (value instanceof List<?>) {
-            return v.visitArray((List<? extends AnnotationValue>) value, p);
-        } else if (value instanceof Boolean) {
-            return v.visitBoolean((boolean) value, p);
-        } else if (value instanceof Byte) {
-            return v.visitByte((byte) value, p);
-        } else if (value instanceof Character) {
-            return v.visitChar((char) value, p);
-        } else if (value instanceof Double) {
-            return v.visitDouble((double) value, p);
-        } else if (value instanceof VariableElement) {
-            return v.visitEnumConstant((VariableElement) value, p);
-        } else if (value instanceof Float) {
-            return v.visitFloat((float) value, p);
-        } else if (value instanceof Integer) {
-            return v.visitInt((int) value, p);
-        } else if (value instanceof Long) {
-            return v.visitLong((long) value, p);
-        } else if (value instanceof Short) {
-            return v.visitShort((short) value, p);
-        } else if (value instanceof String) {
-            return v.visitString((String) value, p);
-        } else if (value instanceof TypeMirror) {
-            return v.visitType((TypeMirror) value, p);
-        } else {
-            return v.visitUnknown(this, p);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeCompilationUnit.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public class CodeCompilationUnit extends CodeElement<TypeElement> {
-
-    public CodeCompilationUnit() {
-        super(Collections.<Modifier> emptySet());
-    }
-
-    @Override
-    public TypeMirror asType() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public ElementKind getKind() {
-        return ElementKind.OTHER;
-    }
-
-    @Override
-    public Name getSimpleName() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public <R, P> R accept(ElementVisitor<R, P> v, P 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.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElement.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,365 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.io.*;
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.codewriter.*;
-
-public abstract class CodeElement<E extends Element> implements Element, GeneratedElement {
-
-    private final Set<Modifier> modifiers;
-    private List<AnnotationMirror> annotations;
-    private List<E> enclosedElements;
-
-    private Element enclosingElement;
-
-    private Element generatorElement;
-    private AnnotationMirror generatorAnnotationMirror;
-
-    public CodeElement() {
-        this.modifiers = new LinkedHashSet<>();
-    }
-
-    public CodeElement(Set<Modifier> modifiers) {
-        this.modifiers = new LinkedHashSet<>(modifiers);
-    }
-
-    @Override
-    public void setGeneratorAnnotationMirror(AnnotationMirror mirror) {
-        this.generatorAnnotationMirror = mirror;
-    }
-
-    @Override
-    public void setGeneratorElement(Element element) {
-        this.generatorElement = element;
-    }
-
-    @Override
-    public AnnotationMirror getGeneratorAnnotationMirror() {
-        return generatorAnnotationMirror;
-    }
-
-    @Override
-    public Element getGeneratorElement() {
-        return generatorElement;
-    }
-
-    public E add(E element) {
-        if (element == null) {
-            throw new NullPointerException();
-        }
-        getEnclosedElements().add(element);
-        return element;
-    }
-
-    public E addOptional(E element) {
-        if (element != null) {
-            add(element);
-        }
-        return element;
-    }
-
-    public void remove(E element) {
-        getEnclosedElements().remove(element);
-    }
-
-    @Override
-    public Set<Modifier> getModifiers() {
-        return modifiers;
-    }
-
-    @Override
-    public List<E> getEnclosedElements() {
-        if (enclosedElements == null) {
-            enclosedElements = parentableList(this, new ArrayList<E>());
-        }
-        return enclosedElements;
-    }
-
-    @Override
-    public List<AnnotationMirror> getAnnotationMirrors() {
-        if (annotations == null) {
-            annotations = parentableList(this, new ArrayList<AnnotationMirror>());
-        }
-        return annotations;
-    }
-
-    /**
-     * Support JDK8 langtools.
-     *
-     * @param annotationType
-     */
-    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Support for some JDK8 builds. (remove after jdk8 is released)
-     *
-     * @param annotationType
-     */
-    public <A extends Annotation> A[] getAnnotations(Class<A> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Support for some JDK8 builds. (remove after jdk8 is released)
-     *
-     * @param annotationType
-     */
-    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-
-    public void addAnnotationMirror(AnnotationMirror annotationMirror) {
-        getAnnotationMirrors().add(annotationMirror);
-    }
-
-    public void removeAnnotationMirror(AnnotationMirror annotationMirror) {
-        getAnnotationMirrors().remove(annotationMirror);
-    }
-
-    protected void setEnclosingElement(Element parent) {
-        this.enclosingElement = parent;
-    }
-
-    public Element getEnclosingElement() {
-        return enclosingElement;
-    }
-
-    public CodeTypeElement getEnclosingClass() {
-        Element p = enclosingElement;
-        while (p != null && p.getKind() != ElementKind.CLASS && p.getKind() != ElementKind.ENUM) {
-            p = p.getEnclosingElement();
-        }
-        return (CodeTypeElement) p;
-    }
-
-    <T> List<T> parentableList(Element parent, List<T> list) {
-        return new ParentableList<>(parent, list);
-    }
-
-    @Override
-    public String toString() {
-        StringBuilderCodeWriter codeWriter = new StringBuilderCodeWriter();
-        accept(codeWriter, null);
-        return codeWriter.getString();
-    }
-
-    private static class StringBuilderCodeWriter extends AbstractCodeWriter {
-
-        public StringBuilderCodeWriter() {
-            this.writer = new CharArrayWriter();
-        }
-
-        @Override
-        protected Writer createWriter(CodeTypeElement clazz) throws IOException {
-            return writer;
-        }
-
-        public String getString() {
-            return new String(((CharArrayWriter) writer).toCharArray()).trim();
-        }
-
-    }
-
-    private static class ParentableList<T> implements List<T> {
-
-        private final Element parent;
-        private final List<T> delegate;
-
-        public ParentableList(Element parent, List<T> delegate) {
-            this.parent = parent;
-            this.delegate = delegate;
-        }
-
-        private void addImpl(T element) {
-            if (element != null) {
-                if (element instanceof CodeElement<?>) {
-                    ((CodeElement<?>) element).setEnclosingElement(parent);
-                }
-            }
-        }
-
-        private static void removeImpl(Object element) {
-            if (element instanceof CodeElement<?>) {
-                ((CodeElement<?>) element).setEnclosingElement(null);
-            }
-        }
-
-        @Override
-        public int size() {
-            return delegate.size();
-        }
-
-        @Override
-        public boolean isEmpty() {
-            return delegate.isEmpty();
-        }
-
-        @Override
-        public boolean contains(Object o) {
-            return delegate.contains(o);
-        }
-
-        @Override
-        public Iterator<T> iterator() {
-            return delegate.iterator();
-        }
-
-        @Override
-        public Object[] toArray() {
-            return delegate.toArray();
-        }
-
-        @Override
-        public <E> E[] toArray(E[] a) {
-            return delegate.toArray(a);
-        }
-
-        @Override
-        public boolean add(T e) {
-            addImpl(e);
-            return delegate.add(e);
-        }
-
-        @Override
-        public boolean remove(Object o) {
-            boolean removed = delegate.remove(o);
-            if (removed) {
-                removeImpl(o);
-            }
-            return removed;
-        }
-
-        @Override
-        public boolean containsAll(Collection<?> c) {
-            return delegate.containsAll(c);
-        }
-
-        @Override
-        public boolean addAll(Collection<? extends T> c) {
-            if (c != null) {
-                for (T t : c) {
-                    addImpl(t);
-                }
-            }
-            return delegate.addAll(c);
-        }
-
-        @Override
-        public boolean addAll(int index, Collection<? extends T> c) {
-            if (c != null) {
-                for (T t : c) {
-                    addImpl(t);
-                }
-            }
-            return delegate.addAll(index, c);
-        }
-
-        @Override
-        public boolean removeAll(Collection<?> c) {
-            if (c != null) {
-                for (Object t : c) {
-                    removeImpl(t);
-                }
-            }
-            return delegate.removeAll(c);
-        }
-
-        @Override
-        public String toString() {
-            return delegate.toString();
-        }
-
-        @Override
-        public boolean retainAll(Collection<?> c) {
-            throw new UnsupportedOperationException("Not supported by parentable list");
-        }
-
-        @Override
-        public void clear() {
-            for (Object e : this) {
-                removeImpl(e);
-            }
-            delegate.clear();
-        }
-
-        @Override
-        public T get(int index) {
-            return delegate.get(index);
-        }
-
-        @Override
-        public T set(int index, T element) {
-            removeImpl(delegate.get(index));
-            addImpl(element);
-            return delegate.set(index, element);
-        }
-
-        @Override
-        public void add(int index, T element) {
-            addImpl(element);
-            delegate.add(index, element);
-        }
-
-        @Override
-        public T remove(int index) {
-            T element = delegate.remove(index);
-            removeImpl(element);
-            return element;
-        }
-
-        @Override
-        public int indexOf(Object o) {
-            return delegate.indexOf(o);
-        }
-
-        @Override
-        public int lastIndexOf(Object o) {
-            return delegate.lastIndexOf(o);
-        }
-
-        @Override
-        public ListIterator<T> listIterator() {
-            return delegate.listIterator();
-        }
-
-        @Override
-        public ListIterator<T> listIterator(int index) {
-            return delegate.listIterator(index);
-        }
-
-        @Override
-        public List<T> subList(int fromIndex, int toIndex) {
-            return new ParentableList<>(parent, delegate.subList(fromIndex, toIndex));
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElementScanner.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import javax.lang.model.element.*;
-import javax.lang.model.util.*;
-
-public abstract class CodeElementScanner<R, P> extends ElementScanner7<R, P> {
-
-    @Override
-    public final R visitExecutable(ExecutableElement e, P p) {
-        return visitExecutable(cast(e, CodeExecutableElement.class), p);
-    }
-
-    public R visitExecutable(CodeExecutableElement e, P p) {
-        R ret = super.visitExecutable(e, p);
-        if (e.getBodyTree() != null) {
-            visitTree(e.getBodyTree(), p);
-        }
-        return ret;
-    }
-
-    @Override
-    public R visitPackage(PackageElement e, P p) {
-        return super.visitPackage(e, p);
-    }
-
-    @Override
-    public final R visitType(TypeElement e, P p) {
-        return visitType(cast(e, CodeTypeElement.class), p);
-    }
-
-    public R visitType(CodeTypeElement e, P p) {
-        return super.visitType(e, p);
-    }
-
-    @Override
-    public R visitTypeParameter(TypeParameterElement e, P p) {
-        return super.visitTypeParameter(e, p);
-    }
-
-    private static <E> E cast(Element element, Class<E> clazz) {
-        return clazz.cast(element);
-    }
-
-    public void visitTree(CodeTree e, P p) {
-        for (CodeTree tree : e.getEnclosedElements()) {
-            tree.acceptCodeElementScanner(this, p);
-        }
-    }
-
-    @SuppressWarnings("unused")
-    public void visitImport(CodeImport e, P p) {
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeExecutableElement.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,212 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-
-public class CodeExecutableElement extends CodeElement<Element> implements ExecutableElement {
-
-    private final List<TypeMirror> throwables = new ArrayList<>();
-    private final List<VariableElement> parameters = parentableList(this, new ArrayList<VariableElement>());
-
-    private TypeMirror returnType;
-    private Name name;
-
-    private CodeTree bodyTree;
-    private String body;
-    private AnnotationValue defaultValue;
-    private boolean varArgs;
-
-    public CodeExecutableElement(TypeMirror returnType, String name) {
-        super(Utils.modifiers());
-        this.returnType = returnType;
-        this.name = CodeNames.of(name);
-    }
-
-    public CodeExecutableElement(Set<Modifier> modifiers, TypeMirror returnType, String name, CodeVariableElement... parameters) {
-        super(modifiers);
-        this.returnType = returnType;
-        this.name = CodeNames.of(name);
-        for (CodeVariableElement codeParameter : parameters) {
-            addParameter(codeParameter);
-        }
-    }
-
-    /* Support JDK8 langtools. */
-    public boolean isDefault() {
-        return false;
-    }
-
-    @Override
-    public List<TypeMirror> getThrownTypes() {
-        return throwables;
-    }
-
-    @Override
-    public TypeMirror asType() {
-        return returnType;
-    }
-
-    @Override
-    public ElementKind getKind() {
-        if (getReturnType() == null) {
-            return ElementKind.CONSTRUCTOR;
-        } else {
-            return ElementKind.METHOD;
-        }
-    }
-
-    @Override
-    public List<? extends TypeParameterElement> getTypeParameters() {
-        return Collections.emptyList();
-    }
-
-    public void setVarArgs(boolean varargs) {
-        this.varArgs = varargs;
-    }
-
-    @Override
-    public boolean isVarArgs() {
-        return varArgs;
-    }
-
-    public void setDefaultValue(AnnotationValue defaultValue) {
-        this.defaultValue = defaultValue;
-    }
-
-    @Override
-    public AnnotationValue getDefaultValue() {
-        return defaultValue;
-    }
-
-    @Override
-    public Name getSimpleName() {
-        return name;
-    }
-
-    public CodeTreeBuilder getBuilder() {
-        CodeTree tree = this.bodyTree;
-        return createBuilder().tree(tree);
-    }
-
-    public CodeTreeBuilder createBuilder() {
-        CodeTreeBuilder builder = new CodeTreeBuilder(null);
-        this.bodyTree = builder.getTree();
-        this.bodyTree.setEnclosingElement(this);
-        this.body = null;
-        return builder;
-    }
-
-    public void setBodyTree(CodeTree body) {
-        this.bodyTree = body;
-    }
-
-    public CodeTree getBodyTree() {
-        return bodyTree;
-    }
-
-    public TypeMirror getReturnType() {
-        return returnType;
-    }
-
-    @Override
-    public List<VariableElement> getParameters() {
-        return parameters;
-    }
-
-    public TypeMirror[] getParameterTypes() {
-        TypeMirror[] types = new TypeMirror[getParameters().size()];
-        for (int i = 0; i < types.length; i++) {
-            types[i] = parameters.get(i).asType();
-        }
-        return types;
-    }
-
-    public void setReturnType(TypeMirror type) {
-        returnType = type;
-    }
-
-    public void addParameter(VariableElement parameter) {
-        parameters.add(parameter);
-    }
-
-    public void removeParameter(VariableElement parameter) {
-        parameters.remove(parameter);
-    }
-
-    public void addThrownType(TypeMirror thrownType) {
-        throwables.add(thrownType);
-    }
-
-    public void removeThrownType(TypeMirror thrownType) {
-        throwables.remove(thrownType);
-    }
-
-    public void setSimpleName(Name name) {
-        this.name = name;
-    }
-
-    public void setBody(String body) {
-        this.body = body;
-    }
-
-    public String getBody() {
-        return body;
-    }
-
-    @Override
-    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        return v.visitExecutable(this, p);
-    }
-
-    public static CodeExecutableElement clone(@SuppressWarnings("unused") ProcessingEnvironment env, ExecutableElement method) {
-        CodeExecutableElement copy = new CodeExecutableElement(method.getReturnType(), method.getSimpleName().toString());
-        for (TypeMirror thrownType : method.getThrownTypes()) {
-            copy.addThrownType(thrownType);
-        }
-        copy.setDefaultValue(method.getDefaultValue());
-
-        for (AnnotationMirror mirror : method.getAnnotationMirrors()) {
-            copy.addAnnotationMirror(mirror);
-        }
-        for (VariableElement var : method.getParameters()) {
-            copy.addParameter(CodeVariableElement.clone(var));
-        }
-        for (Element element : method.getEnclosedElements()) {
-            copy.add(element);
-        }
-        copy.getModifiers().addAll(method.getModifiers());
-        copy.setVarArgs(method.isVarArgs());
-        return copy;
-    }
-
-    public TypeMirror getReceiverType() {
-        throw new UnsupportedOperationException();
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeImport.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import javax.lang.model.type.*;
-
-public class CodeImport implements Comparable<CodeImport> {
-
-    private final TypeMirror importType;
-    private final String importString;
-    private final boolean staticImport;
-
-    public CodeImport(TypeMirror importedType, String importString, boolean staticImport) {
-        this.importType = importedType;
-        this.importString = importString;
-        this.staticImport = staticImport;
-    }
-
-    public TypeMirror getImportType() {
-        return importType;
-    }
-
-    public boolean isStaticImport() {
-        return staticImport;
-    }
-
-    public String getImportString() {
-        return importString;
-    }
-
-    @Override
-    public int compareTo(CodeImport o) {
-        if (staticImport && !o.staticImport) {
-            return 1;
-        } else if (!staticImport && o.staticImport) {
-            return -1;
-        } else {
-            return importString.compareTo(o.getImportString());
-        }
-    }
-
-    public <P> void accept(CodeElementScanner<?, P> s, P p) {
-        s.visitImport(this, p);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((importString == null) ? 0 : importString.hashCode());
-        result = prime * result + (staticImport ? 1231 : 1237);
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        CodeImport other = (CodeImport) obj;
-        if (importString == null) {
-            if (other.importString != null) {
-                return false;
-            }
-        } else if (!importString.equals(other.importString)) {
-            return false;
-        }
-        if (staticImport != other.staticImport) {
-            return false;
-        }
-        return true;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeNames.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-public abstract class CodeNames {
-
-    private static Map<String, Name> names = new HashMap<>();
-
-    public static Name of(String value) {
-        Name name = names.get(value);
-        if (name == null) {
-            name = new NameImpl(value);
-            names.put(value, name);
-        }
-        return name;
-    }
-
-    private static class NameImpl implements Name {
-
-        private final String name;
-
-        public NameImpl(String name) {
-            this.name = name;
-        }
-
-        @Override
-        public int length() {
-            return name.length();
-        }
-
-        @Override
-        public char charAt(int index) {
-            return name.charAt(index);
-        }
-
-        @Override
-        public CharSequence subSequence(int start, int end) {
-            return name.subSequence(start, end);
-        }
-
-        @Override
-        public boolean contentEquals(CharSequence cs) {
-            return name.contentEquals(cs);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof Name) {
-                return ((Name) obj).contentEquals(name);
-            }
-            return super.equals(obj);
-        }
-
-        @Override
-        public int hashCode() {
-            return name.hashCode();
-        }
-
-        @Override
-        public String toString() {
-            return name;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTree.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public class CodeTree extends CodeElement<CodeTree> {
-
-    private final CodeTreeKind kind;
-
-    private TypeMirror type;
-    private final String string;
-
-    CodeTree(CodeTreeKind kind, TypeMirror type, String string) {
-        this.kind = kind;
-        this.type = type;
-        this.string = string;
-    }
-
-    public TypeMirror getType() {
-        return type;
-    }
-
-    public CodeTreeKind getCodeKind() {
-        return kind;
-    }
-
-    public String getString() {
-        return string;
-    }
-
-    public <P> void acceptCodeElementScanner(CodeElementScanner<?, P> s, P p) {
-        s.visitTree(this, p);
-    }
-
-    public void setType(TypeMirror type) {
-        this.type = type;
-    }
-
-    @Override
-    public TypeMirror asType() {
-        return type;
-    }
-
-    @Override
-    public ElementKind getKind() {
-        return ElementKind.OTHER;
-    }
-
-    @Override
-    public Name getSimpleName() {
-        return CodeNames.of(getString());
-    }
-
-    @Override
-    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        if (v instanceof CodeElementScanner<?, ?>) {
-            acceptCodeElementScanner((CodeElementScanner<?, P>) v, p);
-            return null;
-        } else {
-            throw new UnsupportedOperationException();
-        }
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeBuilder.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,888 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import static com.oracle.truffle.dsl.processor.ast.CodeTreeKind.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-
-public class CodeTreeBuilder {
-
-    private final CodeTreeBuilder parent;
-
-    private BuilderCodeTree currentElement;
-    private final BuilderCodeTree root;
-
-    private int treeCount;
-
-    public CodeTreeBuilder(CodeTreeBuilder parent) {
-        this.root = new BuilderCodeTree(GROUP, null, null);
-        this.currentElement = root;
-        this.parent = parent;
-    }
-
-    @Override
-    public String toString() {
-        return root.toString();
-    }
-
-    public int getTreeCount() {
-        return treeCount;
-    }
-
-    public boolean isEmpty() {
-        return treeCount == 0;
-    }
-
-    public CodeTreeBuilder statement(String statement) {
-        return startStatement().string(statement).end();
-    }
-
-    public CodeTreeBuilder statement(CodeTree statement) {
-        return startStatement().tree(statement).end();
-    }
-
-    public static CodeTreeBuilder createBuilder() {
-        return new CodeTreeBuilder(null);
-    }
-
-    public static CodeTree singleString(String s) {
-        return new CodeTreeBuilder(null).string(s).getTree();
-    }
-
-    public static CodeTree singleType(TypeMirror s) {
-        return new CodeTreeBuilder(null).type(s).getTree();
-    }
-
-    private CodeTreeBuilder push(CodeTreeKind kind) {
-        return push(new BuilderCodeTree(kind, null, null));
-    }
-
-    private CodeTreeBuilder push(String string) {
-        return push(new BuilderCodeTree(CodeTreeKind.STRING, null, string));
-    }
-
-    private CodeTreeBuilder push(TypeMirror type) {
-        return push(new BuilderCodeTree(CodeTreeKind.TYPE, type, null));
-    }
-
-    private CodeTreeBuilder push(CodeTreeKind kind, TypeMirror type, String string) {
-        return push(new BuilderCodeTree(kind, type, string));
-    }
-
-    private CodeTreeBuilder push(BuilderCodeTree tree) {
-        if (currentElement != null) {
-            if (!removeLastIfEnqueued(tree)) {
-                return this;
-            }
-            currentElement.add(tree);
-        }
-        switch (tree.getCodeKind()) {
-            case COMMA_GROUP:
-            case GROUP:
-            case INDENT:
-                currentElement = tree;
-                break;
-        }
-        treeCount++;
-        return this;
-    }
-
-    private boolean removeLastIfEnqueued(BuilderCodeTree tree) {
-        if (tree.getCodeKind() == REMOVE_LAST) {
-            return !clearLastRec(tree.removeLast, currentElement.getEnclosedElements());
-        }
-        List<CodeTree> childTree = tree.getEnclosedElements();
-        if (!childTree.isEmpty()) {
-            CodeTree last = childTree.get(0);
-            if (last instanceof BuilderCodeTree) {
-                if (!removeLastIfEnqueued((BuilderCodeTree) last)) {
-                    childTree.remove(0);
-                }
-            }
-        }
-        return true;
-    }
-
-    private void clearLast(CodeTreeKind kind) {
-        if (clearLastRec(kind, currentElement.getEnclosedElements())) {
-            treeCount--;
-        } else {
-            // delay clearing the last
-            BuilderCodeTree tree = new BuilderCodeTree(REMOVE_LAST, null, null);
-            tree.removeLast = kind;
-            push(tree);
-        }
-    }
-
-    public CodeTreeBuilder startStatement() {
-        startGroup();
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-                string(";").newLine();
-            }
-
-            @Override
-            public void afterEnd() {
-            }
-        });
-        return this;
-    }
-
-    public CodeTreeBuilder startGroup() {
-        return push(CodeTreeKind.GROUP);
-    }
-
-    public CodeTreeBuilder startCommaGroup() {
-        return push(CodeTreeKind.COMMA_GROUP);
-    }
-
-    public CodeTreeBuilder startCall(String callSite) {
-        return startCall((CodeTree) null, callSite);
-    }
-
-    public CodeTreeBuilder startCall(String receiver, String callSite) {
-        return startCall(singleString(receiver), callSite);
-    }
-
-    public CodeTreeBuilder startCall(CodeTree receiver, String callSite) {
-        if (receiver == null) {
-            return startGroup().string(callSite).startParanthesesCommaGroup().endAfter();
-        } else {
-            return startGroup().tree(receiver).string(".").string(callSite).startParanthesesCommaGroup().endAfter();
-        }
-    }
-
-    public CodeTreeBuilder startStaticCall(TypeMirror type, String methodName) {
-        return startGroup().push(CodeTreeKind.STATIC_METHOD_REFERENCE, type, methodName).startParanthesesCommaGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startStaticCall(ExecutableElement method) {
-        return startStaticCall(Utils.findNearestEnclosingType(method).asType(), method.getSimpleName().toString());
-    }
-
-    public CodeTreeBuilder staticReference(TypeMirror type, String fieldName) {
-        return push(CodeTreeKind.STATIC_FIELD_REFERENCE, type, fieldName);
-    }
-
-    private CodeTreeBuilder endAndWhitespaceAfter() {
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string(" ");
-                end();
-            }
-        });
-        return this;
-    }
-
-    private CodeTreeBuilder endAfter() {
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                end();
-            }
-        });
-        return this;
-    }
-
-    private CodeTreeBuilder startParanthesesCommaGroup() {
-        startGroup();
-        string("(").startCommaGroup();
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string(")");
-            }
-        });
-        endAfter();
-        return this;
-    }
-
-    private CodeTreeBuilder startCurlyBracesCommaGroup() {
-        startGroup();
-        string("{").startCommaGroup();
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string("}");
-            }
-        });
-        endAfter();
-        return this;
-    }
-
-    public CodeTreeBuilder startParantheses() {
-        startGroup();
-        string("(").startGroup();
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string(")");
-            }
-        });
-        endAfter();
-        return this;
-    }
-
-    public CodeTreeBuilder doubleQuote(String s) {
-        return startGroup().string("\"" + s + "\"").end();
-    }
-
-    public CodeTreeBuilder string(String chunk1) {
-        return push(chunk1);
-    }
-
-    public CodeTreeBuilder string(String chunk1, String chunk2) {
-        return push(GROUP).string(chunk1).string(chunk2).end();
-    }
-
-    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3) {
-        return push(GROUP).string(chunk1).string(chunk2).string(chunk3).end();
-    }
-
-    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4) {
-        return push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4).end();
-    }
-
-    public CodeTreeBuilder tree(CodeTree treeToAdd) {
-        if (treeToAdd instanceof BuilderCodeTree) {
-            return push((BuilderCodeTree) treeToAdd).end();
-        } else {
-            BuilderCodeTree tree = new BuilderCodeTree(GROUP, null, null);
-            tree.add(treeToAdd);
-            return push(tree).end();
-        }
-    }
-
-    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4, String... chunks) {
-        push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4);
-        for (int i = 0; i < chunks.length; i++) {
-            string(chunks[i]);
-        }
-        return end();
-    }
-
-    public CodeTreeBuilder dot() {
-        return string(".");
-    }
-
-    public CodeTreeBuilder newLine() {
-        return push(NEW_LINE);
-    }
-
-    public CodeTreeBuilder startWhile() {
-        return startGroup().string("while ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startDoBlock() {
-        return startGroup().string("do ").startBlock();
-    }
-
-    public CodeTreeBuilder startDoWhile() {
-        clearLast(CodeTreeKind.NEW_LINE);
-        return startStatement().string(" while ").startParanthesesCommaGroup().endAfter().startGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startIf() {
-        return startGroup().string("if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startFor() {
-        return startGroup().string("for ").startParantheses().endAndWhitespaceAfter().startGroup().endAfter();
-    }
-
-    public boolean startIf(boolean elseIf) {
-        if (elseIf) {
-            startElseIf();
-        } else {
-            startIf();
-        }
-        return true;
-    }
-
-    public CodeTreeBuilder startElseIf() {
-        clearLast(CodeTreeKind.NEW_LINE);
-        return startGroup().string(" else if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startElseBlock() {
-        clearLast(CodeTreeKind.NEW_LINE);
-        return startGroup().string(" else ").startBlock().endAfter();
-    }
-
-    private boolean clearLastRec(CodeTreeKind kind, List<CodeTree> children) {
-        for (int i = children.size() - 1; i >= 0; i--) {
-            CodeTree child = children.get(i);
-            if (child.getCodeKind() == kind) {
-                children.remove(children.get(i));
-                return true;
-            } else {
-                if (clearLastRec(kind, child.getEnclosedElements())) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    public CodeTreeBuilder startCase() {
-        startGroup().string("case ");
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-                string(" :").newLine();
-            }
-
-            @Override
-            public void afterEnd() {
-            }
-        });
-        return this;
-    }
-
-    public CodeTreeBuilder caseDefault() {
-        return startGroup().string("default :").newLine().end();
-    }
-
-    public CodeTreeBuilder startSwitch() {
-        return startGroup().string("switch ").startParanthesesCommaGroup().endAndWhitespaceAfter();
-    }
-
-    public CodeTreeBuilder startReturn() {
-        ExecutableElement method = findMethod();
-        if (method != null && Utils.isVoid(method.getReturnType())) {
-            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 ");
-        }
-    }
-
-    public CodeTreeBuilder startAssert() {
-        return startStatement().string("assert ");
-    }
-
-    public CodeTreeBuilder startNewArray(ArrayType arrayType, CodeTree size) {
-        startGroup().string("new ").type(arrayType.getComponentType()).string("[");
-        if (size != null) {
-            tree(size);
-        }
-        string("]");
-        if (size == null) {
-            string(" ");
-            startCurlyBracesCommaGroup().endAfter();
-        }
-        return this;
-    }
-
-    public CodeTreeBuilder startNew(TypeMirror uninializedNodeClass) {
-        return startGroup().string("new ").type(uninializedNodeClass).startParanthesesCommaGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startNew(String typeName) {
-        return startGroup().string("new ").string(typeName).startParanthesesCommaGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startIndention() {
-        return push(CodeTreeKind.INDENT);
-    }
-
-    public CodeTreeBuilder end(int times) {
-        for (int i = 0; i < times; i++) {
-            end();
-        }
-        return this;
-    }
-
-    public CodeTreeBuilder end() {
-        BuilderCodeTree tree = currentElement;
-        EndCallback callback = tree.getAtEndListener();
-        if (callback != null) {
-            callback.beforeEnd();
-            toParent();
-            callback.afterEnd();
-        } else {
-            toParent();
-        }
-        return this;
-    }
-
-    private void toParent() {
-        Element parentElement = currentElement.getEnclosingElement();
-        if (currentElement != root) {
-            this.currentElement = (BuilderCodeTree) parentElement;
-        } else {
-            this.currentElement = root;
-        }
-    }
-
-    public CodeTreeBuilder startBlock() {
-        startGroup();
-        string("{").newLine().startIndention();
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string("}").newLine();
-            }
-        });
-        endAfter();
-        return this;
-    }
-
-    private void registerCallBack(EndCallback callback) {
-        currentElement.registerAtEnd(callback);
-    }
-
-    public CodeTreeBuilder defaultDeclaration(TypeMirror type, String name) {
-        if (!Utils.isVoid(type)) {
-            startStatement();
-            type(type);
-            string(" ");
-            string(name);
-            string(" = ");
-            defaultValue(type);
-            end(); // statement
-        }
-        return this;
-    }
-
-    public CodeTreeBuilder declaration(TypeMirror type, String name, String init) {
-        return declaration(type, name, singleString(init));
-    }
-
-    public CodeTreeBuilder declaration(String type, String name, CodeTree init) {
-        startStatement();
-        string(type);
-        string(" ");
-        string(name);
-        if (init != null) {
-            string(" = ");
-            tree(init);
-        }
-        end(); // statement
-        return this;
-    }
-
-    public CodeTreeBuilder declaration(String type, String name, String init) {
-        return declaration(type, name, singleString(init));
-    }
-
-    public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTree init) {
-        if (Utils.isVoid(type)) {
-            startStatement();
-            tree(init);
-            end();
-        } else {
-            startStatement();
-            type(type);
-            string(" ");
-            string(name);
-            if (init != null) {
-                string(" = ");
-                tree(init);
-            }
-            end(); // statement
-        }
-        return this;
-    }
-
-    public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTreeBuilder init) {
-        if (init == this) {
-            throw new IllegalArgumentException("Recursive builder usage.");
-        }
-        return declaration(type, name, init.getTree());
-    }
-
-    public CodeTreeBuilder declaration(String type, String name, CodeTreeBuilder init) {
-        if (init == this) {
-            throw new IllegalArgumentException("Recursive builder usage.");
-        }
-        return declaration(type, name, init.getTree());
-    }
-
-    public CodeTreeBuilder declaration(TypeMirror type, String name) {
-        return declaration(type, name, (CodeTree) null);
-    }
-
-    public CodeTreeBuilder create() {
-        return new CodeTreeBuilder(this);
-    }
-
-    public CodeTreeBuilder type(TypeMirror type) {
-        return push(type);
-    }
-
-    public CodeTreeBuilder typeLiteral(TypeMirror type) {
-        return startGroup().type(type).string(".class").end();
-    }
-
-    private void assertRoot() {
-        if (currentElement != root) {
-            throw new IllegalStateException("CodeTreeBuilder was not ended properly.");
-        }
-    }
-
-    public CodeTreeBuilder startCaseBlock() {
-        return startIndention();
-    }
-
-    public CodeTreeBuilder startThrow() {
-        return startStatement().string("throw ");
-    }
-
-    public CodeTree getTree() {
-        assertRoot();
-        return root;
-    }
-
-    public CodeTree getRoot() {
-        return root;
-    }
-
-    public CodeTreeBuilder cast(String baseClassName) {
-        string("(").string(baseClassName).string(") ");
-        return this;
-    }
-
-    public CodeTreeBuilder cast(TypeMirror type, CodeTree content) {
-        if (Utils.isVoid(type)) {
-            tree(content);
-            return this;
-        } else if (type.getKind() == TypeKind.DECLARED && Utils.getQualifiedName(type).equals("java.lang.Object")) {
-            tree(content);
-            return this;
-        } else {
-            return startGroup().string("(").type(type).string(")").string(" ").tree(content).end();
-        }
-    }
-
-    public CodeTreeBuilder startSuperCall() {
-        return string("super").startParanthesesCommaGroup();
-    }
-
-    public CodeTreeBuilder returnFalse() {
-        return startReturn().string("false").end();
-    }
-
-    public CodeTreeBuilder returnStatement() {
-        return statement("return");
-    }
-
-    public ExecutableElement findMethod() {
-        Element element = currentElement;
-        while (element != null && (element.getKind() != ElementKind.METHOD && (element.getKind() != ElementKind.CONSTRUCTOR))) {
-            element = element.getEnclosingElement();
-        }
-        ExecutableElement found = element != null ? (ExecutableElement) element : null;
-        if (found == null && parent != null) {
-            found = parent.findMethod();
-        }
-        return found;
-    }
-
-    public CodeTreeBuilder returnNull() {
-        return startReturn().string("null").end();
-    }
-
-    public CodeTreeBuilder returnTrue() {
-        return startReturn().string("true").end();
-    }
-
-    public CodeTreeBuilder instanceOf(CodeTree var, CodeTree type) {
-        tree(var).string(" instanceof ").tree(type);
-        return this;
-    }
-
-    public CodeTreeBuilder instanceOf(String var, String type) {
-        return instanceOf(singleString(var), singleString(type));
-    }
-
-    public CodeTreeBuilder instanceOf(String var, TypeMirror type) {
-        TypeElement element = Utils.fromTypeMirror(type);
-        if (element == null) {
-            throw new IllegalArgumentException("Cannot call instanceof for a non supported type: " + type.getKind());
-        }
-        return instanceOf(singleString(var), singleType(type));
-    }
-
-    public CodeTreeBuilder defaultValue(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case VOID:
-                return string("");
-            case ARRAY:
-            case DECLARED:
-            case PACKAGE:
-            case NULL:
-                return string("null");
-            case BOOLEAN:
-                return string("false");
-            case BYTE:
-                return string("(byte) 0");
-            case CHAR:
-                return string("(char) 0");
-            case DOUBLE:
-                return string("0.0D");
-            case LONG:
-                return string("0L");
-            case INT:
-                return string("0");
-            case FLOAT:
-                return string("0.0F");
-            case SHORT:
-                return string("(short) 0");
-            default:
-                throw new AssertionError();
-        }
-    }
-
-    public CodeTreeBuilder assertFalse() {
-        return startAssert().string("false").end();
-    }
-
-    public CodeTreeBuilder breakStatement() {
-        return statement("break");
-    }
-
-    public CodeTreeBuilder isNull() {
-        return string(" == null");
-    }
-
-    public CodeTreeBuilder isNotNull() {
-        return string(" != null");
-    }
-
-    public CodeTreeBuilder is(CodeTree tree) {
-        return string(" == ").tree(tree);
-    }
-
-    public CodeTreeBuilder startTryBlock() {
-        return string("try ").startBlock();
-    }
-
-    public CodeTreeBuilder startCatchBlock(TypeMirror exceptionType, String localVarName) {
-        clearLast(CodeTreeKind.NEW_LINE);
-        string(" catch (").type(exceptionType).string(" ").string(localVarName).string(") ");
-        return startBlock();
-    }
-
-    public CodeTreeBuilder startFinallyBlock() {
-        clearLast(CodeTreeKind.NEW_LINE);
-        string(" finally ");
-        return startBlock();
-    }
-
-    public CodeTreeBuilder nullLiteral() {
-        return string("null");
-    }
-
-    private static class BuilderCodeTree extends CodeTree {
-
-        private EndCallback atEndListener;
-        private CodeTreeKind removeLast;
-
-        public BuilderCodeTree(CodeTreeKind kind, TypeMirror type, String string) {
-            super(kind, type, string);
-        }
-
-        public void registerAtEnd(EndCallback atEnd) {
-            if (this.atEndListener != null) {
-                this.atEndListener = new CompoundCallback(this.atEndListener, atEnd);
-            } else {
-                this.atEndListener = atEnd;
-            }
-        }
-
-        public EndCallback getAtEndListener() {
-            return atEndListener;
-        }
-
-        @Override
-        public String toString() {
-            final StringBuilder b = new StringBuilder();
-            acceptCodeElementScanner(new Printer(b), null);
-            return b.toString();
-        }
-
-        private static class CompoundCallback implements EndCallback {
-
-            private final EndCallback callback1;
-            private final EndCallback callback2;
-
-            public CompoundCallback(EndCallback callback1, EndCallback callback2) {
-                this.callback1 = callback1;
-                this.callback2 = callback2;
-            }
-
-            @Override
-            public void afterEnd() {
-                callback1.afterEnd();
-                callback2.afterEnd();
-            }
-
-            @Override
-            public void beforeEnd() {
-                callback1.beforeEnd();
-                callback1.beforeEnd();
-            }
-        }
-
-    }
-
-    private interface EndCallback {
-
-        void beforeEnd();
-
-        void afterEnd();
-    }
-
-    private static class Printer extends CodeElementScanner<Void, Void> {
-
-        private int indent;
-        private boolean newLine;
-        private final String ln = "\n";
-
-        private final StringBuilder b;
-
-        Printer(StringBuilder b) {
-            this.b = b;
-        }
-
-        @Override
-        public void visitTree(CodeTree e, Void p) {
-            switch (e.getCodeKind()) {
-                case COMMA_GROUP:
-                    List<CodeTree> children = e.getEnclosedElements();
-                    for (int i = 0; i < children.size(); i++) {
-                        children.get(i).acceptCodeElementScanner(this, p);
-                        if (i < e.getEnclosedElements().size() - 1) {
-                            b.append(", ");
-                        }
-                    }
-                    break;
-                case GROUP:
-                    super.visitTree(e, p);
-                    break;
-                case INDENT:
-                    indent();
-                    super.visitTree(e, p);
-                    dedent();
-                    break;
-                case NEW_LINE:
-                    writeLn();
-                    break;
-                case STRING:
-                    if (e.getString() != null) {
-                        write(e.getString());
-                    } else {
-                        write("null");
-                    }
-                    break;
-                case TYPE:
-                    write(Utils.getSimpleName(e.getType()));
-                    break;
-                default:
-                    assert false;
-                    return;
-            }
-        }
-
-        private void indent() {
-            indent++;
-        }
-
-        private void dedent() {
-            indent--;
-        }
-
-        private void writeLn() {
-            write(ln);
-            newLine = true;
-        }
-
-        private void write(String m) {
-            if (newLine && m != ln) {
-                writeIndent();
-                newLine = false;
-            }
-            b.append(m);
-        }
-
-        private void writeIndent() {
-            for (int i = 0; i < indent; i++) {
-                b.append("    ");
-            }
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeKind.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-public enum CodeTreeKind {
-    STATIC_FIELD_REFERENCE,
-    STATIC_METHOD_REFERENCE,
-    GROUP,
-    COMMA_GROUP,
-    REMOVE_LAST,
-    INDENT,
-    STRING,
-    NEW_LINE,
-    TYPE;
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeElement.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.DeclaredCodeTypeMirror;
-
-public class CodeTypeElement extends CodeElement<Element> implements TypeElement {
-
-    private final List<? extends CodeImport> imports = parentableList(this, new ArrayList<CodeImport>());
-
-    private final PackageElement packageElement;
-
-    private final Name simpleName;
-    private final Name packageName;
-    private Name qualifiedName;
-
-    private final List<TypeMirror> implementsInterfaces = new ArrayList<>();
-    private final ElementKind kind;
-    private TypeMirror superClass;
-
-    private final DeclaredCodeTypeMirror mirror = new DeclaredCodeTypeMirror(this);
-
-    public CodeTypeElement(Set<Modifier> modifiers, ElementKind kind, PackageElement packageElement, String simpleName) {
-        super(modifiers);
-        this.kind = kind;
-        this.packageElement = packageElement;
-        this.simpleName = CodeNames.of(simpleName);
-        if (this.packageElement != null) {
-            this.packageName = packageElement.getQualifiedName();
-        } else {
-            this.packageName = CodeNames.of("default");
-        }
-        this.qualifiedName = createQualifiedName();
-    }
-
-    @Override
-    public TypeMirror asType() {
-        return mirror;
-    }
-
-    @Override
-    public ElementKind getKind() {
-        return kind;
-    }
-
-    public boolean containsField(String name) {
-        for (VariableElement field : getFields()) {
-            if (field.getSimpleName().toString().equals(name)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public NestingKind getNestingKind() {
-        return isTopLevelClass() ? NestingKind.TOP_LEVEL : NestingKind.LOCAL;
-    }
-
-    @Override
-    public Element getEnclosingElement() {
-        if (isTopLevelClass()) {
-            return packageElement;
-        } else {
-            return super.getEnclosingElement();
-        }
-    }
-
-    @Override
-    public TypeMirror getSuperclass() {
-        return superClass;
-    }
-
-    @Override
-    public List<TypeMirror> getInterfaces() {
-        return implementsInterfaces;
-    }
-
-    @Override
-    public List<? extends TypeParameterElement> getTypeParameters() {
-        return Collections.emptyList();
-    }
-
-    public boolean isTopLevelClass() {
-        return super.getEnclosingElement() instanceof CodeCompilationUnit;
-    }
-
-    private Name createQualifiedName() {
-        TypeElement enclosingType = getEnclosingClass();
-        if (enclosingType == null) {
-            return CodeNames.of(packageName + "." + simpleName);
-        } else {
-            return CodeNames.of(enclosingType.getQualifiedName() + "." + simpleName);
-        }
-    }
-
-    @Override
-    protected void setEnclosingElement(Element element) {
-        super.setEnclosingElement(element);
-
-        // update qualified name on container change
-        this.qualifiedName = createQualifiedName();
-    }
-
-    public Name getPackageName() {
-        return packageName;
-    }
-
-    @Override
-    public Name getQualifiedName() {
-        return qualifiedName;
-    }
-
-    @Override
-    public Name getSimpleName() {
-        return simpleName;
-    }
-
-    public void setSuperClass(TypeMirror superType) {
-        this.superClass = superType;
-    }
-
-    public List<? extends CodeImport> getImports() {
-        return imports;
-    }
-
-    public List<TypeMirror> getImplements() {
-        return implementsInterfaces;
-    }
-
-    @Override
-    public int hashCode() {
-        return getQualifiedName().hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == this) {
-            return true;
-        } else if (obj instanceof TypeElement) {
-            return getQualifiedName().equals(((TypeElement) obj).getQualifiedName());
-        }
-        return false;
-    }
-
-    public List<VariableElement> getFields() {
-        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());
-    }
-
-    public List<TypeElement> getInnerClasses() {
-        return ElementFilter.typesIn(getEnclosedElements());
-    }
-
-    @Override
-    public String toString() {
-        return getQualifiedName().toString();
-    }
-
-    @Override
-    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        return v.visitType(this, p);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeMirror.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public class CodeTypeMirror implements TypeMirror {
-
-    private final TypeKind kind;
-
-    public CodeTypeMirror(TypeKind kind) {
-        this.kind = kind;
-    }
-
-    @Override
-    public TypeKind getKind() {
-        return kind;
-    }
-
-    @Override
-    public <R, P> R accept(TypeVisitor<R, P> v, P p) {
-        throw new UnsupportedOperationException();
-    }
-
-    public static class ArrayCodeTypeMirror extends CodeTypeMirror implements ArrayType {
-
-        private final TypeMirror component;
-
-        public ArrayCodeTypeMirror(TypeMirror component) {
-            super(TypeKind.ARRAY);
-            this.component = component;
-        }
-
-        @Override
-        public TypeMirror getComponentType() {
-            return component;
-        }
-
-    }
-
-    public static class DeclaredCodeTypeMirror extends CodeTypeMirror implements DeclaredType {
-
-        private final TypeElement clazz;
-        private final List<? extends TypeMirror> typeArguments;
-
-        public DeclaredCodeTypeMirror(TypeElement clazz) {
-            this(clazz, Collections.<TypeMirror> emptyList());
-        }
-
-        public DeclaredCodeTypeMirror(TypeElement clazz, List<? extends TypeMirror> typeArguments) {
-            super(TypeKind.DECLARED);
-            this.clazz = clazz;
-            this.typeArguments = typeArguments;
-        }
-
-        @Override
-        public Element asElement() {
-            return clazz;
-        }
-
-        @Override
-        public TypeMirror getEnclosingType() {
-            return clazz.getEnclosingElement().asType();
-        }
-
-        @Override
-        public List<? extends TypeMirror> getTypeArguments() {
-            return typeArguments;
-        }
-
-        @Override
-        public String toString() {
-            return clazz.getQualifiedName().toString();
-        }
-
-    }
-
-    public List<? extends AnnotationMirror> getAnnotationMirrors() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @param annotationType
-     */
-    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @param annotationType
-     */
-    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeVariableElement.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-
-public final class CodeVariableElement extends CodeElement<Element> implements VariableElement {
-
-    private Name name;
-    private TypeMirror type;
-    private Object constantValue;
-
-    private CodeTree init;
-
-    public CodeVariableElement(TypeMirror type, String name) {
-        super(Utils.modifiers());
-        this.type = type;
-        this.name = CodeNames.of(name);
-    }
-
-    public CodeVariableElement(Set<Modifier> modifiers, TypeMirror type, String name) {
-        super(modifiers);
-        this.type = type;
-        this.name = CodeNames.of(name);
-    }
-
-    public CodeVariableElement(Set<Modifier> modifiers, TypeMirror type, String name, String init) {
-        this(modifiers, type, name);
-        if (init != null) {
-            this.init = new CodeTree(CodeTreeKind.STRING, null, init);
-        }
-    }
-
-    public CodeTreeBuilder createInitBuilder() {
-        CodeTreeBuilder builder = new CodeTreeBuilder(null);
-        init = builder.getTree();
-        init.setEnclosingElement(this);
-        return builder;
-    }
-
-    public void setInit(CodeTree init) {
-        this.init = init;
-    }
-
-    public CodeTree getInit() {
-        return init;
-    }
-
-    public Name getSimpleName() {
-        return name;
-    }
-
-    public TypeMirror getType() {
-        return type;
-    }
-
-    @Override
-    public TypeMirror asType() {
-        return type;
-    }
-
-    @Override
-    public ElementKind getKind() {
-        if (getEnclosingElement() instanceof ExecutableElement) {
-            return ElementKind.PARAMETER;
-        } else if (getEnclosingElement() instanceof TypeElement) {
-            return ElementKind.FIELD;
-        } else {
-            return ElementKind.PARAMETER;
-        }
-    }
-
-    public void setConstantValue(Object constantValue) {
-        this.constantValue = constantValue;
-    }
-
-    @Override
-    public Object getConstantValue() {
-        return constantValue;
-    }
-
-    public String getName() {
-        return getSimpleName().toString();
-    }
-
-    public void setSimpleName(Name name) {
-        this.name = name;
-    }
-
-    public void setName(String name) {
-        this.name = CodeNames.of(name);
-    }
-
-    public void setType(TypeMirror type) {
-        this.type = type;
-    }
-
-    @Override
-    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        return v.visitVariable(this, p);
-    }
-
-    public static CodeVariableElement clone(VariableElement var) {
-        CodeVariableElement copy = new CodeVariableElement(var.getModifiers(), var.asType(), var.getSimpleName().toString());
-        copy.setConstantValue(var.getConstantValue());
-        for (AnnotationMirror mirror : var.getAnnotationMirrors()) {
-            copy.addAnnotationMirror(mirror);
-        }
-        for (Element element : var.getEnclosedElements()) {
-            copy.add(element);
-        }
-        return copy;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/GeneratedElement.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import javax.lang.model.element.*;
-
-public interface GeneratedElement {
-
-    AnnotationMirror getGeneratorAnnotationMirror();
-
-    void setGeneratorAnnotationMirror(AnnotationMirror mirror);
-
-    Element getGeneratorElement();
-
-    void setGeneratorElement(Element element);
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/GeneratedPackageElement.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public final class GeneratedPackageElement extends CodeElement<Element> implements PackageElement {
-
-    private final Name qualifiedName;
-    private final Name simpleName;
-
-    public GeneratedPackageElement(String qualifiedName) {
-        this.qualifiedName = CodeNames.of(qualifiedName);
-        int lastIndex = qualifiedName.lastIndexOf('.');
-        if (lastIndex == -1) {
-            simpleName = CodeNames.of("");
-        } else {
-            simpleName = CodeNames.of(qualifiedName.substring(lastIndex, qualifiedName.length()));
-        }
-    }
-
-    public TypeMirror asType() {
-        throw new UnsupportedOperationException();
-    }
-
-    public ElementKind getKind() {
-        return ElementKind.PACKAGE;
-    }
-
-    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        return v.visitPackage(this, p);
-    }
-
-    public Name getQualifiedName() {
-        return qualifiedName;
-    }
-
-    public Name getSimpleName() {
-        return simpleName;
-    }
-
-    public boolean isUnnamed() {
-        return simpleName.toString().equals("");
-    }
-
-    @Override
-    public int hashCode() {
-        return qualifiedName.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof PackageElement) {
-            return qualifiedName.equals(((PackageElement) obj).getQualifiedName());
-        }
-        return super.equals(obj);
-    }
-}
\ No newline at end of file
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/GeneratedTypeElement.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-public final class GeneratedTypeElement extends CodeTypeElement {
-
-    public GeneratedTypeElement(Set<Modifier> modifiers, ElementKind kind, PackageElement packageElement, String simpleName) {
-        super(modifiers, kind, packageElement, simpleName);
-        setEnclosingElement(packageElement);
-    }
-
-}
\ No newline at end of file
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/GeneratedTypeMirror.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.ast;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.DeclaredCodeTypeMirror;
-
-public final class GeneratedTypeMirror extends DeclaredCodeTypeMirror {
-
-    public GeneratedTypeMirror(String packageName, String name) {
-        super(new GeneratedTypeElement(Collections.<Modifier> emptySet(), ElementKind.CLASS, new GeneratedPackageElement(packageName), name));
-    }
-
-}
\ No newline at end of file
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,764 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.codewriter;
-
-import static com.oracle.truffle.dsl.processor.Utils.*;
-
-import java.io.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-
-public abstract class AbstractCodeWriter extends CodeElementScanner<Void, Void> {
-
-    private static final int MAX_LINE_LENGTH = 200;
-    private static final int LINE_WRAP_INDENTS = 3;
-    private static final String IDENT_STRING = "    ";
-    private static final String LN = "\n"; /* unix style */
-
-    protected Writer writer;
-    private int indent;
-    private boolean newLine;
-    private int lineLength;
-    private boolean lineWrapping = false;
-
-    private OrganizedImports imports;
-
-    public void visitCompilationUnit(CodeCompilationUnit e) {
-        for (TypeElement clazz : e.getEnclosedElements()) {
-            clazz.accept(this, null);
-        }
-    }
-
-    protected abstract Writer createWriter(CodeTypeElement clazz) throws IOException;
-
-    @Override
-    public Void visitType(CodeTypeElement e, Void p) {
-        if (e.isTopLevelClass()) {
-            Writer w = null;
-            try {
-                imports = OrganizedImports.organize(e);
-                w = new TrimTrailingSpaceWriter(createWriter(e));
-                writer = w;
-                writeRootClass(e);
-            } catch (IOException ex) {
-                throw new RuntimeException(ex);
-            } finally {
-                if (w != null) {
-                    try {
-                        w.close();
-                    } catch (Throwable e1) {
-                        // see eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=361378
-                        // TODO temporary suppress errors on close.
-                    }
-                }
-                writer = null;
-            }
-        } else {
-            writeClassImpl(e);
-        }
-        return null;
-    }
-
-    private void writeRootClass(CodeTypeElement e) {
-        writeHeader();
-        write("package ").write(e.getPackageName()).write(";").writeLn();
-        writeEmptyLn();
-
-        Set<CodeImport> generateImports = imports.generateImports();
-        List<CodeImport> typeImports = new ArrayList<>();
-        List<CodeImport> staticImports = new ArrayList<>();
-
-        for (CodeImport codeImport : generateImports) {
-            if (codeImport.isStaticImport()) {
-                staticImports.add(codeImport);
-            } else {
-                typeImports.add(codeImport);
-            }
-        }
-        Collections.sort(typeImports);
-        Collections.sort(staticImports);
-
-        for (CodeImport imp : staticImports) {
-            imp.accept(this, null);
-            writeLn();
-        }
-        if (!staticImports.isEmpty()) {
-            writeEmptyLn();
-        }
-
-        for (CodeImport imp : typeImports) {
-            imp.accept(this, null);
-            writeLn();
-        }
-        if (!typeImports.isEmpty()) {
-            writeEmptyLn();
-        }
-
-        writeClassImpl(e);
-    }
-
-    private String useImport(Element enclosedType, TypeMirror type) {
-        if (imports != null) {
-            return imports.createTypeReference(enclosedType, type);
-        } else {
-            return Utils.getSimpleName(type);
-        }
-    }
-
-    private void writeClassImpl(CodeTypeElement e) {
-        for (AnnotationMirror annotation : e.getAnnotationMirrors()) {
-            visitAnnotation(e, annotation);
-            writeLn();
-        }
-
-        writeModifiers(e.getModifiers());
-        if (e.getKind() == ElementKind.ENUM) {
-            write("enum ");
-        } else {
-            write("class ");
-        }
-        write(e.getSimpleName());
-        if (e.getSuperclass() != null && !getQualifiedName(e.getSuperclass()).equals("java.lang.Object")) {
-            write(" extends ").write(useImport(e, e.getSuperclass()));
-        }
-        if (e.getImplements().size() > 0) {
-            write(" implements ");
-            for (int i = 0; i < e.getImplements().size(); i++) {
-                write(useImport(e, e.getImplements().get(i)));
-                if (i < e.getImplements().size() - 1) {
-                    write(", ");
-                }
-            }
-        }
-
-        write(" {").writeLn();
-        writeEmptyLn();
-        indent(1);
-
-        List<VariableElement> staticFields = getStaticFields(e);
-        List<VariableElement> instanceFields = getInstanceFields(e);
-
-        for (int i = 0; i < staticFields.size(); i++) {
-            VariableElement field = staticFields.get(i);
-            field.accept(this, null);
-            if (e.getKind() == ElementKind.ENUM && i < staticFields.size() - 1) {
-                write(",");
-                writeLn();
-            } else {
-                write(";");
-                writeLn();
-            }
-        }
-
-        if (staticFields.size() > 0) {
-            writeEmptyLn();
-        }
-
-        for (VariableElement field : instanceFields) {
-            field.accept(this, null);
-            write(";");
-            writeLn();
-        }
-        if (instanceFields.size() > 0) {
-            writeEmptyLn();
-        }
-
-        for (ExecutableElement method : ElementFilter.constructorsIn(e.getEnclosedElements())) {
-            method.accept(this, null);
-        }
-
-        for (ExecutableElement method : getInstanceMethods(e)) {
-            method.accept(this, null);
-        }
-
-        for (ExecutableElement method : getStaticMethods(e)) {
-            method.accept(this, null);
-        }
-
-        for (TypeElement clazz : e.getInnerClasses()) {
-            clazz.accept(this, null);
-        }
-
-        dedent(1);
-        write("}");
-        writeEmptyLn();
-    }
-
-    private static List<VariableElement> getStaticFields(CodeTypeElement clazz) {
-        List<VariableElement> staticFields = new ArrayList<>();
-        for (VariableElement field : clazz.getFields()) {
-            if (field.getModifiers().contains(Modifier.STATIC)) {
-                staticFields.add(field);
-            }
-        }
-        return staticFields;
-    }
-
-    private static List<VariableElement> getInstanceFields(CodeTypeElement clazz) {
-        List<VariableElement> instanceFields = new ArrayList<>();
-        for (VariableElement field : clazz.getFields()) {
-            if (!field.getModifiers().contains(Modifier.STATIC)) {
-                instanceFields.add(field);
-            }
-        }
-        return instanceFields;
-    }
-
-    private static List<ExecutableElement> getStaticMethods(CodeTypeElement clazz) {
-        List<ExecutableElement> staticMethods = new ArrayList<>();
-        for (ExecutableElement method : clazz.getMethods()) {
-            if (method.getModifiers().contains(Modifier.STATIC)) {
-                staticMethods.add(method);
-            }
-        }
-        return staticMethods;
-    }
-
-    private static List<ExecutableElement> getInstanceMethods(CodeTypeElement clazz) {
-        List<ExecutableElement> instanceMethods = new ArrayList<>();
-        for (ExecutableElement method : clazz.getMethods()) {
-            if (!method.getModifiers().contains(Modifier.STATIC)) {
-                instanceMethods.add(method);
-            }
-        }
-        return instanceMethods;
-    }
-
-    @Override
-    public Void visitVariable(VariableElement f, Void p) {
-        Element parent = f.getEnclosingElement();
-
-        for (AnnotationMirror annotation : f.getAnnotationMirrors()) {
-            visitAnnotation(f, annotation);
-            write(" ");
-        }
-
-        CodeTree init = null;
-        if (f instanceof CodeVariableElement) {
-            init = ((CodeVariableElement) f).getInit();
-        }
-
-        if (parent.getKind() == ElementKind.ENUM && f.getModifiers().contains(Modifier.STATIC)) {
-            write(f.getSimpleName());
-            if (init != null) {
-                write("(");
-                init.acceptCodeElementScanner(this, p);
-                write(")");
-            }
-        } else {
-            Element enclosing = f.getEnclosingElement();
-            writeModifiers(f.getModifiers());
-
-            boolean varArgs = false;
-            if (enclosing.getKind() == ElementKind.METHOD) {
-                ExecutableElement method = (ExecutableElement) enclosing;
-                if (method.isVarArgs() && method.getParameters().indexOf(f) == method.getParameters().size() - 1) {
-                    varArgs = true;
-                }
-            }
-
-            TypeMirror varType = f.asType();
-            if (varArgs) {
-                if (varType.getKind() == TypeKind.ARRAY) {
-                    varType = ((ArrayType) varType).getComponentType();
-                }
-                write(useImport(f, varType));
-                write("...");
-            } else {
-                write(useImport(f, varType));
-            }
-
-            write(" ");
-            write(f.getSimpleName());
-            if (init != null) {
-                write(" = ");
-                init.acceptCodeElementScanner(this, p);
-            }
-        }
-        return null;
-    }
-
-    public void visitAnnotation(Element enclosedElement, AnnotationMirror e) {
-        write("@").write(useImport(enclosedElement, e.getAnnotationType()));
-
-        if (!e.getElementValues().isEmpty()) {
-            write("(");
-            final ExecutableElement defaultElement = findExecutableElement(e.getAnnotationType(), "value");
-
-            Map<? extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues();
-            if (defaultElement != null && values.size() == 1 && values.get(defaultElement) != null) {
-                visitAnnotationValue(enclosedElement, values.get(defaultElement));
-            } else {
-                Set<? extends ExecutableElement> methodsSet = values.keySet();
-                List<ExecutableElement> methodsList = new ArrayList<>();
-                for (ExecutableElement method : methodsSet) {
-                    if (values.get(method) == null) {
-                        continue;
-                    }
-                    methodsList.add(method);
-                }
-
-                Collections.sort(methodsList, new Comparator<ExecutableElement>() {
-
-                    @Override
-                    public int compare(ExecutableElement o1, ExecutableElement o2) {
-                        return o1.getSimpleName().toString().compareTo(o2.getSimpleName().toString());
-                    }
-                });
-
-                for (int i = 0; i < methodsList.size(); i++) {
-                    ExecutableElement method = methodsList.get(i);
-                    AnnotationValue value = values.get(method);
-                    write(method.getSimpleName().toString());
-                    write(" = ");
-                    visitAnnotationValue(enclosedElement, value);
-
-                    if (i < methodsList.size() - 1) {
-                        write(", ");
-                    }
-                }
-            }
-
-            write(")");
-        }
-    }
-
-    public void visitAnnotationValue(Element enclosedElement, AnnotationValue e) {
-        e.accept(new AnnotationValueWriterVisitor(enclosedElement), null);
-    }
-
-    private class AnnotationValueWriterVisitor extends AbstractAnnotationValueVisitor7<Void, Void> {
-
-        private final Element enclosedElement;
-
-        public AnnotationValueWriterVisitor(Element enclosedElement) {
-            this.enclosedElement = enclosedElement;
-        }
-
-        @Override
-        public Void visitBoolean(boolean b, Void p) {
-            write(Boolean.toString(b));
-            return null;
-        }
-
-        @Override
-        public Void visitByte(byte b, Void p) {
-            write(Byte.toString(b));
-            return null;
-        }
-
-        @Override
-        public Void visitChar(char c, Void p) {
-            write(Character.toString(c));
-            return null;
-        }
-
-        @Override
-        public Void visitDouble(double d, Void p) {
-            write(Double.toString(d));
-            return null;
-        }
-
-        @Override
-        public Void visitFloat(float f, Void p) {
-            write(Float.toString(f));
-            return null;
-        }
-
-        @Override
-        public Void visitInt(int i, Void p) {
-            write(Integer.toString(i));
-            return null;
-        }
-
-        @Override
-        public Void visitLong(long i, Void p) {
-            write(Long.toString(i));
-            return null;
-        }
-
-        @Override
-        public Void visitShort(short s, Void p) {
-            write(Short.toString(s));
-            return null;
-        }
-
-        @Override
-        public Void visitString(String s, Void p) {
-            write("\"");
-            write(s);
-            write("\"");
-            return null;
-        }
-
-        @Override
-        public Void visitType(TypeMirror t, Void p) {
-            write(useImport(enclosedElement, t));
-            write(".class");
-            return null;
-        }
-
-        @Override
-        public Void visitEnumConstant(VariableElement c, Void p) {
-            write(useImport(enclosedElement, c.asType()));
-            write(".");
-            write(c.getSimpleName().toString());
-            return null;
-        }
-
-        @Override
-        public Void visitAnnotation(AnnotationMirror a, Void p) {
-            AbstractCodeWriter.this.visitAnnotation(enclosedElement, a);
-            return null;
-        }
-
-        @Override
-        public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
-            write("{");
-            for (int i = 0; i < vals.size(); i++) {
-                AnnotationValue value = vals.get(i);
-                AbstractCodeWriter.this.visitAnnotationValue(enclosedElement, value);
-                if (i < vals.size() - 1) {
-                    write(", ");
-                }
-            }
-            write("}");
-            return null;
-        }
-    }
-
-    public ExecutableElement findExecutableElement(DeclaredType type, String name) {
-        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements());
-        for (ExecutableElement executableElement : elements) {
-            if (executableElement.getSimpleName().toString().equals(name)) {
-                return executableElement;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public void visitImport(CodeImport e, Void p) {
-        if (e.isStaticImport()) {
-            write("import static ").write(e.getImportString()).write(";");
-        } else {
-            write("import ").write(e.getImportString()).write(";");
-        }
-    }
-
-    @Override
-    public Void visitExecutable(CodeExecutableElement e, Void p) {
-        for (AnnotationMirror annotation : e.getAnnotationMirrors()) {
-            visitAnnotation(e, annotation);
-            writeLn();
-        }
-
-        writeModifiers(e.getModifiers());
-
-        if (e.getReturnType() != null) {
-            write(useImport(e, e.getReturnType()));
-            write(" ");
-        }
-        write(e.getSimpleName());
-        write("(");
-
-        for (int i = 0; i < e.getParameters().size(); i++) {
-            VariableElement param = e.getParameters().get(i);
-            param.accept(this, p);
-            if (i < e.getParameters().size() - 1) {
-                write(", ");
-            }
-        }
-        write(")");
-
-        List<TypeMirror> throwables = e.getThrownTypes();
-        if (throwables.size() > 0) {
-            write(" throws ");
-            for (int i = 0; i < throwables.size(); i++) {
-                write(useImport(e, throwables.get(i)));
-                if (i < throwables.size() - 1) {
-                    write(", ");
-                }
-            }
-        }
-
-        if (e.getModifiers().contains(Modifier.ABSTRACT)) {
-            writeLn(";");
-        } else if (e.getBodyTree() != null) {
-            writeLn(" {");
-            indent(1);
-            e.getBodyTree().acceptCodeElementScanner(this, p);
-            dedent(1);
-            writeLn("}");
-        } else if (e.getBody() != null) {
-            write(" {");
-            write(e.getBody());
-            writeLn("}");
-        } else {
-            writeLn("{ }");
-        }
-        writeEmptyLn();
-        return null;
-    }
-
-    @Override
-    public void visitTree(CodeTree e, Void p) {
-        CodeTreeKind kind = e.getCodeKind();
-
-        switch (kind) {
-            case COMMA_GROUP:
-                List<CodeTree> children = e.getEnclosedElements();
-                for (int i = 0; i < children.size(); i++) {
-                    children.get(i).acceptCodeElementScanner(this, p);
-                    if (i < e.getEnclosedElements().size() - 1) {
-                        write(", ");
-                    }
-                }
-                break;
-            case GROUP:
-                for (CodeTree tree : e.getEnclosedElements()) {
-                    tree.acceptCodeElementScanner(this, p);
-                }
-                break;
-            case INDENT:
-                indent(1);
-                for (CodeTree tree : e.getEnclosedElements()) {
-                    tree.acceptCodeElementScanner(this, p);
-                }
-                dedent(1);
-                break;
-            case NEW_LINE:
-                writeLn();
-                break;
-            case STRING:
-                if (e.getString() != null) {
-                    write(e.getString());
-                } else {
-                    write("null");
-                }
-                break;
-            case STATIC_FIELD_REFERENCE:
-                if (e.getString() != null) {
-                    write(imports.createStaticFieldReference(e, e.getType(), e.getString()));
-                } else {
-                    write("null");
-                }
-                break;
-            case STATIC_METHOD_REFERENCE:
-                if (e.getString() != null) {
-                    write(imports.createStaticMethodReference(e, e.getType(), e.getString()));
-                } else {
-                    write("null");
-                }
-                break;
-            case TYPE:
-                write(useImport(e, e.getType()));
-                break;
-            default:
-                assert false;
-                return;
-        }
-    }
-
-    protected void writeHeader() {
-        // default implementation does nothing
-    }
-
-    private void writeModifiers(Set<Modifier> modifiers) {
-        if (modifiers != null) {
-            for (Modifier modifier : modifiers) {
-                write(modifier.toString());
-                write(" ");
-            }
-        }
-    }
-
-    protected void indent(int count) {
-        indent += count;
-    }
-
-    protected void dedent(int count) {
-        indent -= count;
-    }
-
-    protected void writeLn() {
-        writeLn("");
-    }
-
-    protected void writeLn(String text) {
-        write(text);
-        write(LN);
-        lineLength = 0;
-        newLine = true;
-        if (lineWrapping) {
-            dedent(LINE_WRAP_INDENTS);
-            lineWrapping = false;
-        }
-        lineWrapping = false;
-    }
-
-    protected void writeEmptyLn() {
-        writeLn();
-    }
-
-    private AbstractCodeWriter write(Name name) {
-        return write(name.toString());
-    }
-
-    private AbstractCodeWriter write(String m) {
-        if (m.isEmpty()) {
-            return this;
-        }
-        try {
-            String s = m;
-            lineLength += s.length();
-            if (newLine && s != LN) {
-                writeIndent();
-                newLine = false;
-            }
-            if (lineLength > MAX_LINE_LENGTH) {
-                s = wrapLine(s);
-            }
-            writer.write(s);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        return this;
-    }
-
-    private String wrapLine(String m) throws IOException {
-        assert !m.isEmpty();
-
-        char firstCharacter = m.charAt(0);
-        char lastCharacter = m.charAt(m.length() - 1);
-        if (firstCharacter == '\"' && lastCharacter == '\"') {
-            // string line wrapping
-            String string = m.substring(1, m.length() - 1);
-            if (string.isEmpty()) {
-                return m;
-            }
-
-            // restore original line length
-            lineLength = lineLength - m.length();
-            int size = 0;
-            for (int i = 0; i < string.length(); i += size) {
-                if (i != 0) {
-                    write("+ ");
-                }
-
-                int nextSize = MAX_LINE_LENGTH - lineLength - 2;
-                if (nextSize <= 0) {
-                    writeLn();
-                    nextSize = MAX_LINE_LENGTH - lineLength - 2;
-                }
-
-                int end = Math.min(i + nextSize, string.length());
-
-                // TODO(CH): fails in normal usage - output ok though
-                // assert lineLength + (end - i) + 2 < MAX_LINE_LENGTH;
-
-                write("\"" + string.substring(i, end) + "\"");
-                size = nextSize;
-            }
-
-            return "";
-        } else if (!Character.isAlphabetic(firstCharacter) && firstCharacter != '+') {
-            return m;
-        }
-
-        if (!lineWrapping) {
-            indent(LINE_WRAP_INDENTS);
-        }
-        lineWrapping = true;
-        lineLength = 0;
-        write(LN);
-        writeIndent();
-        return m;
-    }
-
-    private void writeIndent() throws IOException {
-        lineLength += indentSize();
-        for (int i = 0; i < indent; i++) {
-            writer.write(IDENT_STRING);
-        }
-    }
-
-    private int indentSize() {
-        return IDENT_STRING.length() * indent;
-    }
-
-    private static class TrimTrailingSpaceWriter extends Writer {
-
-        private final Writer delegate;
-        private final StringBuilder buffer = new StringBuilder();
-
-        public TrimTrailingSpaceWriter(Writer delegate) {
-            this.delegate = delegate;
-        }
-
-        @Override
-        public void close() throws IOException {
-            this.delegate.close();
-        }
-
-        @Override
-        public void flush() throws IOException {
-            this.delegate.flush();
-        }
-
-        @Override
-        public void write(char[] cbuf, int off, int len) throws IOException {
-            buffer.append(cbuf, off, len);
-            int newLinePoint = buffer.indexOf(LN);
-
-            if (newLinePoint != -1) {
-                String lhs = trimTrailing(buffer.substring(0, newLinePoint));
-                delegate.write(lhs);
-                delegate.write(LN);
-                buffer.delete(0, newLinePoint + 1);
-            }
-        }
-
-        private static String trimTrailing(String s) {
-            int cut = 0;
-            for (int i = s.length() - 1; i >= 0; i--) {
-                if (Character.isWhitespace(s.charAt(i))) {
-                    cut++;
-                } else {
-                    break;
-                }
-            }
-            if (cut > 0) {
-                return s.substring(0, s.length() - cut);
-            }
-            return s;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/FixWarningsVisitor.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.codewriter;
-
-import static com.oracle.truffle.dsl.processor.Utils.*;
-import static javax.lang.model.element.Modifier.*;
-
-import java.io.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-
-public class FixWarningsVisitor extends CodeElementScanner<Void, Void> {
-
-    private final Set<String> symbolsUsed = new HashSet<>();
-
-    private final ProcessorContext context;
-    private final DeclaredType unusedAnnotation;
-    private final DeclaredType overrideType;
-
-    public FixWarningsVisitor(ProcessorContext context, DeclaredType unusedAnnotation, DeclaredType overrideType) {
-        this.context = context;
-        this.unusedAnnotation = unusedAnnotation;
-        this.overrideType = overrideType;
-    }
-
-    @Override
-    public Void visitType(CodeTypeElement e, Void p) {
-        List<TypeElement> superTypes = Utils.getSuperTypes(e);
-        for (TypeElement type : superTypes) {
-            String qualifiedName = Utils.getQualifiedName(type);
-            if (qualifiedName.equals(Serializable.class.getCanonicalName())) {
-                if (!e.containsField("serialVersionUID")) {
-                    e.add(new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), context.getType(long.class), "serialVersionUID", "1L"));
-                }
-                break;
-            }
-        }
-
-        return super.visitType(e, p);
-    }
-
-    @Override
-    public Void visitExecutable(CodeExecutableElement e, Void p) {
-        if (e.getParameters().isEmpty()) {
-            return null;
-        } else if (e.getModifiers().contains(Modifier.ABSTRACT)) {
-            return null;
-        } else if (containsOverride(e)) {
-            return null;
-        }
-
-        symbolsUsed.clear();
-        super.visitExecutable(e, p);
-
-        for (VariableElement parameter : e.getParameters()) {
-            if (!symbolsUsed.contains(parameter.getSimpleName().toString())) {
-                e.getAnnotationMirrors().add(createUnusedAnnotationMirror());
-                break;
-            }
-        }
-        return null;
-    }
-
-    private boolean containsOverride(CodeExecutableElement e) {
-        for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
-            if (Utils.typeEquals(overrideType, mirror.getAnnotationType())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private CodeAnnotationMirror createUnusedAnnotationMirror() {
-        CodeAnnotationMirror mirror = new CodeAnnotationMirror(unusedAnnotation);
-        mirror.setElementValue(mirror.findExecutableElement("value"), new CodeAnnotationValue("unused"));
-        return mirror;
-    }
-
-    @Override
-    public void visitTree(CodeTree e, Void p) {
-        if (e.getString() != null) {
-            computeSymbols(e.getString());
-        }
-        super.visitTree(e, p);
-    }
-
-    private void computeSymbols(String s) {
-        // TODO there should not be any need for a StringTokenizer if we have a real AST for
-        // method bodies. Also the current solution is not perfect. What if one token
-        // is spread across multiple CodeTree instances? But for now that works.
-        StringTokenizer tokenizer = new StringTokenizer(s, ".= :,()[];{}\"\"'' ", false);
-        while (tokenizer.hasMoreElements()) {
-            String token = tokenizer.nextToken().trim();
-            if (token.length() > 0) {
-                symbolsUsed.add(token);
-            }
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/GenerateOverrideVisitor.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.codewriter;
-
-import static com.oracle.truffle.dsl.processor.Utils.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-
-public class GenerateOverrideVisitor extends CodeElementScanner<Void, Void> {
-
-    private final DeclaredType overrideType;
-
-    public GenerateOverrideVisitor(DeclaredType overrideType) {
-        this.overrideType = overrideType;
-    }
-
-    @Override
-    public Void visitExecutable(CodeExecutableElement e, Void p) {
-        if (!e.getModifiers().contains(Modifier.STATIC) && !e.getModifiers().contains(Modifier.PRIVATE)) {
-            String name = e.getSimpleName().toString();
-            TypeMirror[] params = e.getParameterTypes();
-
-            for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
-                if (Utils.typeEquals(overrideType, mirror.getAnnotationType())) {
-                    // already declared (may happen if method copied from super class)
-                    return super.visitExecutable(e, p);
-                }
-            }
-
-            if (isDeclaredMethodInSuperType(e.getEnclosingClass(), name, params)) {
-                e.addAnnotationMirror(new CodeAnnotationMirror(overrideType));
-            }
-        }
-        return super.visitExecutable(e, p);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,489 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.codewriter;
-
-import static com.oracle.truffle.dsl.processor.Utils.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-
-public final class OrganizedImports {
-
-    private final Set<TypeMirror> staticImportUsage = new HashSet<>();
-
-    private final Map<String, TypeMirror> simpleNamesUsed = new HashMap<>();
-
-    private final Set<String> declaredStaticMethods = new HashSet<>();
-    private final Set<String> declaredStaticFields = new HashSet<>();
-    private final Set<String> ambiguousStaticMethods = new HashSet<>();
-    private final Set<String> ambiguousStaticFields = new HashSet<>();
-
-    private final CodeTypeElement topLevelClass;
-
-    private OrganizedImports(CodeTypeElement topLevelClass) {
-        this.topLevelClass = topLevelClass;
-    }
-
-    public static OrganizedImports organize(CodeTypeElement topLevelClass) {
-        OrganizedImports organized = new OrganizedImports(topLevelClass);
-        organized.organizeImpl();
-        return organized;
-    }
-
-    private void organizeImpl() {
-        ImportTypeReferenceVisitor reference = new ImportTypeReferenceVisitor();
-        topLevelClass.accept(reference, null);
-
-        processStaticImports(topLevelClass);
-        List<TypeElement> types = Utils.getSuperTypes(topLevelClass);
-        for (TypeElement typeElement : types) {
-            processStaticImports(typeElement);
-        }
-
-        for (TypeMirror type : staticImportUsage) {
-            TypeElement element = fromTypeMirror(type);
-            if (element != null) {
-                // already processed by supertype
-                if (types.contains(element)) {
-                    continue;
-                }
-                processStaticImports(element);
-            }
-        }
-    }
-
-    public String createTypeReference(Element enclosedElement, TypeMirror type) {
-        switch (type.getKind()) {
-            case BOOLEAN:
-            case BYTE:
-            case CHAR:
-            case DOUBLE:
-            case FLOAT:
-            case SHORT:
-            case INT:
-            case LONG:
-            case VOID:
-                return Utils.getSimpleName(type);
-            case DECLARED:
-                return createDeclaredTypeName(enclosedElement, (DeclaredType) type);
-            case ARRAY:
-                return createTypeReference(enclosedElement, ((ArrayType) type).getComponentType()) + "[]";
-            case WILDCARD:
-                return createWildcardName(enclosedElement, (WildcardType) type);
-            case TYPEVAR:
-                return "?";
-            default:
-                throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type);
-        }
-    }
-
-    public String createStaticFieldReference(Element enclosedElement, TypeMirror type, String fieldName) {
-        return createStaticReference(enclosedElement, type, fieldName, ambiguousStaticFields);
-    }
-
-    public String createStaticMethodReference(Element enclosedElement, TypeMirror type, String methodName) {
-        return createStaticReference(enclosedElement, type, methodName, ambiguousStaticMethods);
-    }
-
-    private String createStaticReference(Element enclosedElement, TypeMirror type, String name, Set<String> ambiguousSymbols) {
-        if (ambiguousSymbols.contains(name)) {
-            // ambiguous import
-            return createTypeReference(enclosedElement, type) + "." + name;
-        } else {
-            // import declared and not ambiguous
-            return name;
-        }
-    }
-
-    private String createWildcardName(Element enclosedElement, WildcardType type) {
-        StringBuilder b = new StringBuilder();
-        if (type.getExtendsBound() != null) {
-            b.append("? extends ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
-        } else if (type.getSuperBound() != null) {
-            b.append("? super ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
-        }
-        return b.toString();
-    }
-
-    private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) {
-        String name;
-        name = Utils.fixECJBinaryNameIssue(type.asElement().getSimpleName().toString());
-
-        if (needsImport(enclosedElement, type)) {
-            TypeMirror usedByType = simpleNamesUsed.get(name);
-            if (usedByType == null) {
-                simpleNamesUsed.put(name, type);
-                usedByType = type;
-            }
-
-            if (!typeEquals(type, usedByType)) {
-                name = getQualifiedName(type);
-            }
-        }
-
-        if (type.getTypeArguments().size() == 0) {
-            return name;
-        }
-
-        StringBuilder b = new StringBuilder(name);
-        b.append("<");
-        if (type.getTypeArguments().size() > 0) {
-            for (int i = 0; i < type.getTypeArguments().size(); i++) {
-                b.append(createTypeReference(enclosedElement, type.getTypeArguments().get(i)));
-                if (i < type.getTypeArguments().size() - 1) {
-                    b.append(", ");
-                }
-            }
-        }
-        b.append(">");
-        return b.toString();
-    }
-
-    public Set<CodeImport> generateImports() {
-        Set<CodeImport> imports = new HashSet<>();
-
-        imports.addAll(generateImports(simpleNamesUsed.values()));
-        imports.addAll(generateStaticImports(staticImportUsage));
-
-        return imports;
-    }
-
-    boolean processStaticImports(TypeElement element) {
-        Set<String> importedMethods = new HashSet<>();
-        List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements());
-        for (ExecutableElement method : methods) {
-            if (method.getModifiers().contains(Modifier.STATIC)) {
-                importedMethods.add(method.getSimpleName().toString());
-            }
-        }
-
-        boolean allMethodsAmbiguous = processStaticImportElements(importedMethods, this.ambiguousStaticMethods, this.declaredStaticMethods);
-
-        Set<String> importedFields = new HashSet<>();
-        List<VariableElement> fields = ElementFilter.fieldsIn(element.getEnclosedElements());
-        for (VariableElement field : fields) {
-            if (field.getModifiers().contains(Modifier.STATIC)) {
-                importedFields.add(field.getSimpleName().toString());
-            }
-        }
-
-        boolean allFieldsAmbiguous = processStaticImportElements(importedFields, this.ambiguousStaticFields, this.declaredStaticFields);
-
-        return allMethodsAmbiguous && allFieldsAmbiguous;
-    }
-
-    private static boolean processStaticImportElements(Set<String> newElements, Set<String> ambiguousElements, Set<String> declaredElements) {
-        boolean allAmbiguous = false;
-        if (declaredElements.containsAll(newElements)) {
-            // all types already declared -> we can remove the import completely -> they will all
-            // get ambiguous
-            allAmbiguous = true;
-        }
-        Set<String> newAmbiguous = new HashSet<>();
-        Set<String> newDeclared = new HashSet<>();
-
-        for (String newElement : newElements) {
-            if (declaredElements.contains(newElement)) {
-                newAmbiguous.add(newElement);
-            } else if (ambiguousElements.contains(newElement)) {
-                // nothing to do
-            } else {
-                newDeclared.add(newElement);
-            }
-        }
-
-        ambiguousElements.addAll(newAmbiguous);
-        declaredElements.addAll(newDeclared);
-        return allAmbiguous;
-    }
-
-    private boolean needsImport(Element enclosedElement, TypeMirror importType) {
-        String importPackagName = getPackageName(importType);
-        if (importPackagName == null) {
-            return false;
-        } else if (importPackagName.equals("java.lang")) {
-            return false;
-        } else if (importPackagName.equals(getPackageName(topLevelClass)) && Utils.isTopLevelClass(importType)) {
-            return false; // same package name -> no import
-        }
-
-        List<Element> elements = Utils.getElementHierarchy(enclosedElement);
-
-        Set<String> autoImportedTypes = new HashSet<>();
-        for (Element element : elements) {
-            if (element.getKind().isClass()) {
-                collectSuperTypeImports((TypeElement) element, autoImportedTypes);
-                collectInnerTypeImports((TypeElement) element, autoImportedTypes);
-            }
-        }
-
-        String qualifiedName = getQualifiedName(importType);
-        if (autoImportedTypes.contains(qualifiedName)) {
-            return false;
-        }
-
-        return true;
-    }
-
-    private static Set<CodeImport> generateImports(Collection<TypeMirror> toGenerate) {
-        TreeSet<CodeImport> importObjects = new TreeSet<>();
-        for (TypeMirror importType : toGenerate) {
-            importObjects.add(new CodeImport(importType, getQualifiedName(importType), false));
-        }
-        return importObjects;
-    }
-
-    private static void collectInnerTypeImports(TypeElement e, Set<String> autoImportedTypes) {
-        autoImportedTypes.add(getQualifiedName(e));
-        for (TypeElement innerClass : ElementFilter.typesIn(e.getEnclosedElements())) {
-            collectInnerTypeImports(innerClass, autoImportedTypes);
-        }
-    }
-
-    private static void collectSuperTypeImports(TypeElement e, Set<String> autoImportedTypes) {
-        List<TypeElement> superTypes = getSuperTypes(e);
-        for (TypeElement superType : superTypes) {
-            List<TypeElement> declaredTypes = getDeclaredTypes(superType);
-            for (TypeElement declaredType : declaredTypes) {
-                autoImportedTypes.add(getQualifiedName(declaredType));
-            }
-        }
-    }
-
-    private Set<CodeImport> generateStaticImports(Set<TypeMirror> toGenerate) {
-        Set<String> autoImportedStaticTypes = new HashSet<>();
-
-        // if type is declared inside a super type of this class -> no import
-        autoImportedStaticTypes.add(getQualifiedName(topLevelClass));
-        autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(topLevelClass));
-
-        TreeSet<CodeImport> importObjects = new TreeSet<>();
-        for (TypeMirror importType : toGenerate) {
-            if (getPackageName(importType) == null) {
-                continue; // no package name -> no import
-            }
-
-            String qualifiedName = getQualifiedName(importType);
-            if (autoImportedStaticTypes.contains(qualifiedName)) {
-                continue;
-            }
-
-            importObjects.add(new CodeImport(importType, qualifiedName + ".*", true));
-        }
-
-        return importObjects;
-    }
-
-    private abstract static class TypeReferenceVisitor extends CodeElementScanner<Void, Void> {
-
-        @Override
-        public void visitTree(CodeTree e, Void p) {
-            if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) {
-                visitStaticFieldReference(e, e.getType(), e.getString());
-            } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) {
-                visitStaticMethodReference(e, e.getType(), e.getString());
-            } else if (e.getType() != null) {
-                visitTypeReference(e, e.getType());
-            }
-            super.visitTree(e, p);
-        }
-
-        @Override
-        public Void visitExecutable(CodeExecutableElement e, Void p) {
-            visitAnnotations(e, e.getAnnotationMirrors());
-            if (e.getReturnType() != null) {
-                visitTypeReference(e, e.getReturnType());
-            }
-            for (TypeMirror type : e.getThrownTypes()) {
-                visitTypeReference(e, type);
-            }
-            return super.visitExecutable(e, p);
-        }
-
-        @Override
-        public Void visitType(CodeTypeElement e, Void p) {
-            visitAnnotations(e, e.getAnnotationMirrors());
-
-            visitTypeReference(e, e.getSuperclass());
-            for (TypeMirror type : e.getImplements()) {
-                visitTypeReference(e, type);
-            }
-
-            return super.visitType(e, p);
-        }
-
-        private void visitAnnotations(Element enclosingElement, List<? extends AnnotationMirror> mirrors) {
-            for (AnnotationMirror mirror : mirrors) {
-                visitAnnotation(enclosingElement, mirror);
-            }
-        }
-
-        public void visitAnnotation(Element enclosingElement, AnnotationMirror e) {
-            visitTypeReference(enclosingElement, e.getAnnotationType());
-            if (!e.getElementValues().isEmpty()) {
-                Map<? extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues();
-                Set<? extends ExecutableElement> methodsSet = values.keySet();
-                List<ExecutableElement> methodsList = new ArrayList<>();
-                for (ExecutableElement method : methodsSet) {
-                    if (values.get(method) == null) {
-                        continue;
-                    }
-                    methodsList.add(method);
-                }
-
-                for (int i = 0; i < methodsList.size(); i++) {
-                    AnnotationValue value = values.get(methodsList.get(i));
-                    visitAnnotationValue(enclosingElement, value);
-                }
-            }
-        }
-
-        public void visitAnnotationValue(Element enclosingElement, AnnotationValue e) {
-            e.accept(new AnnotationValueReferenceVisitor(enclosingElement), null);
-        }
-
-        private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7<Void, Void> {
-
-            private final Element enclosingElement;
-
-            public AnnotationValueReferenceVisitor(Element enclosedElement) {
-                this.enclosingElement = enclosedElement;
-            }
-
-            @Override
-            public Void visitBoolean(boolean b, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitByte(byte b, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitChar(char c, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitDouble(double d, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitFloat(float f, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitInt(int i, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitLong(long i, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitShort(short s, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitString(String s, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitType(TypeMirror t, Void p) {
-                visitTypeReference(enclosingElement, t);
-                return null;
-            }
-
-            @Override
-            public Void visitEnumConstant(VariableElement c, Void p) {
-                visitTypeReference(enclosingElement, c.asType());
-                return null;
-            }
-
-            @Override
-            public Void visitAnnotation(AnnotationMirror a, Void p) {
-                TypeReferenceVisitor.this.visitAnnotation(enclosingElement, a);
-                return null;
-            }
-
-            @Override
-            public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
-                for (int i = 0; i < vals.size(); i++) {
-                    TypeReferenceVisitor.this.visitAnnotationValue(enclosingElement, vals.get(i));
-                }
-                return null;
-            }
-        }
-
-        @Override
-        public Void visitVariable(VariableElement f, Void p) {
-            visitAnnotations(f, f.getAnnotationMirrors());
-            visitTypeReference(f, f.asType());
-            return super.visitVariable(f, p);
-        }
-
-        @Override
-        public void visitImport(CodeImport e, Void p) {
-        }
-
-        public abstract void visitTypeReference(Element enclosedType, TypeMirror type);
-
-        public abstract void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName);
-
-        public abstract void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName);
-
-    }
-
-    private class ImportTypeReferenceVisitor extends TypeReferenceVisitor {
-
-        @Override
-        public void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName) {
-            staticImportUsage.add(type);
-        }
-
-        @Override
-        public void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName) {
-            staticImportUsage.add(type);
-        }
-
-        @Override
-        public void visitTypeReference(Element enclosedType, TypeMirror type) {
-            createTypeReference(enclosedType, type);
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/AbstractCompiler.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.compiler;
-
-import java.lang.reflect.*;
-
-public abstract class AbstractCompiler implements Compiler {
-
-    protected static Object method(Object o, String methodName) throws Exception {
-        Method method = o.getClass().getMethod(methodName);
-        method.setAccessible(true);
-        return method.invoke(o);
-    }
-
-    protected static Object method(Object o, String methodName, Class<?>[] paramTypes, Object... values) throws Exception {
-        Method method = o.getClass().getMethod(methodName, paramTypes);
-        method.setAccessible(true);
-        return method.invoke(o, values);
-    }
-
-    protected static Object field(Object o, String fieldName) throws Exception {
-        if (o == null) {
-            return null;
-        }
-        Class<?> clazz = o.getClass();
-        Field field = null;
-        try {
-            field = clazz.getField(fieldName);
-        } catch (NoSuchFieldException e) {
-            while (clazz != null) {
-                try {
-                    field = clazz.getDeclaredField(fieldName);
-                    break;
-                } catch (NoSuchFieldException e1) {
-                    clazz = clazz.getSuperclass();
-                }
-            }
-            if (field == null) {
-                throw e;
-            }
-        }
-        field.setAccessible(true);
-        return field.get(o);
-    }
-
-    protected static String parseHeader(String content) {
-        int index = content.indexOf("/*");
-        if (index == -1) {
-            return null;
-        }
-        if (!content.substring(0, index).trim().equals("")) {
-            // just whitespace before
-            return null;
-        }
-
-        int endIndex = content.indexOf("*/", index);
-        if (endIndex == -1) {
-            return null;
-        }
-        return content.substring(index, endIndex + 2);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/Compiler.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.compiler;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-
-public interface Compiler {
-
-    String getMethodBody(ProcessingEnvironment env, ExecutableElement method);
-
-    String getHeaderComment(ProcessingEnvironment env, Element type);
-
-    List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type);
-
-    List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type);
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/CompilerFactory.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.compiler;
-
-import javax.lang.model.element.*;
-
-public class CompilerFactory {
-
-    private static Compiler javac;
-    private static Compiler jdt;
-
-    public static Compiler getCompiler(Element currentElement) {
-        if (JavaCCompiler.isValidElement(currentElement)) {
-            if (javac == null) {
-                javac = new JavaCCompiler();
-            }
-            return javac;
-        } else if (JDTCompiler.isValidElement(currentElement)) {
-            if (jdt == null) {
-                jdt = new JDTCompiler();
-            }
-            return jdt;
-        } else {
-            throw new UnsupportedOperationException("Unsupported compiler for element " + currentElement.getClass().getName() + ".");
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JDTCompiler.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,283 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.compiler;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-
-public class JDTCompiler extends AbstractCompiler {
-
-    public static boolean isValidElement(Element currentElement) {
-        try {
-            Class<?> elementClass = Class.forName("org.eclipse.jdt.internal.compiler.apt.model.ElementImpl");
-            return elementClass.isAssignableFrom(currentElement.getClass());
-        } catch (ClassNotFoundException e) {
-            return false;
-        }
-    }
-
-    public List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) {
-        return sortBySourceOrder(new ArrayList<>(environment.getElementUtils().getAllMembers(type)));
-    }
-
-    public List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type) {
-        return sortBySourceOrder(new ArrayList<>(type.getEnclosedElements()));
-    }
-
-    private static List<? extends Element> sortBySourceOrder(List<Element> elements) {
-        final Map<TypeElement, List<Object>> declarationOrders = new HashMap<>();
-
-        Collections.sort(elements, new Comparator<Element>() {
-            public int compare(Element o1, Element o2) {
-                try {
-                    TypeMirror enclosing1 = o1.getEnclosingElement().asType();
-                    TypeMirror enclosing2 = o2.getEnclosingElement().asType();
-
-                    if (Utils.typeEquals(enclosing1, enclosing2)) {
-                        List<Object> declarationOrder = lookupDeclarationOrder(declarationOrders, (TypeElement) o1.getEnclosingElement());
-                        if (declarationOrder == null) {
-                            return 0;
-                        }
-                        Object o1Binding = field(o1, "_binding");
-                        Object o2Binding = field(o2, "_binding");
-
-                        int i1 = declarationOrder.indexOf(o1Binding);
-                        int i2 = declarationOrder.indexOf(o2Binding);
-
-                        return i1 - i2;
-                    } else {
-                        if (Utils.isSubtype(enclosing1, enclosing2)) {
-                            return 1;
-                        } else if (Utils.isSubtype(enclosing2, enclosing1)) {
-                            return -1;
-                        } else {
-                            return 0;
-                        }
-                    }
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        });
-        return elements;
-    }
-
-    private static List<Object> lookupDeclarationOrder(Map<TypeElement, List<Object>> declarationOrders, TypeElement type) throws Exception, ClassNotFoundException {
-        if (declarationOrders.containsKey(type)) {
-            return declarationOrders.get(type);
-        }
-
-        Object binding = field(type, "_binding");
-        Class<?> sourceTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding");
-        Class<?> binaryTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding");
-
-        List<Object> declarationOrder = null;
-        if (sourceTypeBinding.isAssignableFrom(binding.getClass())) {
-            declarationOrder = findSourceTypeOrder(binding);
-        } else if (binaryTypeBinding.isAssignableFrom(binding.getClass())) {
-            declarationOrder = findBinaryTypeOrder(binding);
-        }
-
-        declarationOrders.put(type, declarationOrder);
-
-        return declarationOrder;
-    }
-
-    private static List<Object> findBinaryTypeOrder(Object binding) throws Exception {
-        Object binaryType = lookupBinaryType(binding);
-        final Object[] sortedMethods = (Object[]) method(binaryType, "getMethods");
-
-        List<Object> sortedElements = new ArrayList<>();
-        if (sortedMethods != null) {
-            sortedElements.addAll(Arrays.asList(sortedMethods));
-        }
-        final Object[] sortedFields = (Object[]) method(binaryType, "getFields");
-        if (sortedFields != null) {
-            sortedElements.addAll(Arrays.asList(sortedFields));
-        }
-        final Object[] sortedTypes = (Object[]) method(binaryType, "getMemberTypes", new Class[0]);
-        if (sortedTypes != null) {
-            sortedElements.addAll(Arrays.asList(sortedTypes));
-        }
-
-        Collections.sort(sortedElements, new Comparator<Object>() {
-            public int compare(Object o1, Object o2) {
-                try {
-                    int structOffset1 = (int) field(o1, "structOffset");
-                    int structOffset2 = (int) field(o2, "structOffset");
-                    return structOffset1 - structOffset2;
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        });
-
-        Class<?> binaryMethod = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryMethod");
-        Class<?> binaryField = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryField");
-        Class<?> nestedType = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryNestedType");
-
-        List<Object> bindings = new ArrayList<>();
-        for (Object sortedElement : sortedElements) {
-            Class<?> elementClass = sortedElement.getClass();
-            if (binaryMethod.isAssignableFrom(elementClass)) {
-                char[] selector = (char[]) method(sortedElement, "getSelector");
-                Object[] foundBindings = (Object[]) method(binding, "getMethods", new Class[]{char[].class}, selector);
-                if (foundBindings == null || foundBindings.length == 0) {
-                    continue;
-                } else if (foundBindings.length == 1) {
-                    bindings.add(foundBindings[0]);
-                } else {
-                    char[] idescriptor = (char[]) method(sortedElement, "getMethodDescriptor");
-                    for (Object foundBinding : foundBindings) {
-                        char[] descriptor = (char[]) method(foundBinding, "signature");
-                        if (descriptor == null && idescriptor == null || Arrays.equals(descriptor, idescriptor)) {
-                            bindings.add(foundBinding);
-                            break;
-                        }
-                    }
-                }
-            } else if (binaryField.isAssignableFrom(elementClass)) {
-                char[] selector = (char[]) method(sortedElement, "getName");
-                Object foundField = method(binding, "getField", new Class[]{char[].class, boolean.class}, selector, true);
-                if (foundField != null) {
-                    bindings.add(foundField);
-                }
-            } else if (nestedType.isAssignableFrom(elementClass)) {
-                char[] selector = (char[]) method(sortedElement, "getSourceName");
-                Object foundType = method(binding, "getMemberType", new Class[]{char[].class}, selector);
-                if (foundType != null) {
-                    bindings.add(foundType);
-                }
-            } else {
-                throw new AssertionError("Unexpected encountered type " + elementClass);
-            }
-        }
-
-        return bindings;
-    }
-
-    private static Object lookupBinaryType(Object binding) throws Exception {
-        Object lookupEnvironment = field(binding, "environment");
-        Object compoundClassName = field(binding, "compoundName");
-        Object nameEnvironment = field(lookupEnvironment, "nameEnvironment");
-        Object nameEnvironmentAnswer = method(nameEnvironment, "findType", new Class[]{char[][].class}, compoundClassName);
-        Object binaryType = method(nameEnvironmentAnswer, "getBinaryType", new Class[0]);
-        return binaryType;
-    }
-
-    private static List<Object> findSourceTypeOrder(Object binding) throws Exception {
-        Object referenceContext = field(field(binding, "scope"), "referenceContext");
-
-        TreeMap<Integer, Object> orderedBindings = new TreeMap<>();
-
-        collectSourceOrder(orderedBindings, referenceContext, "methods");
-        collectSourceOrder(orderedBindings, referenceContext, "fields");
-        collectSourceOrder(orderedBindings, referenceContext, "memberTypes");
-
-        return new ArrayList<>(orderedBindings.values());
-    }
-
-    private static void collectSourceOrder(TreeMap<Integer, Object> orderedBindings, Object referenceContext, String fieldName) throws Exception {
-        Object[] declarations = (Object[]) field(referenceContext, fieldName);
-        if (declarations != null) {
-            for (int i = 0; i < declarations.length; i++) {
-                Integer declarationSourceStart = (Integer) field(declarations[i], "declarationSourceStart");
-                orderedBindings.put(declarationSourceStart, field(declarations[i], "binding"));
-            }
-        }
-    }
-
-    @Override
-    public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
-        try {
-
-            char[] source = getSource(method);
-            if (source == null) {
-                return null;
-            }
-
-            /*
-             * 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");
-
-            int length = bodyEnd - bodyStart;
-            char[] target = new char[length];
-            System.arraycopy(source, bodyStart, target, 0, length);
-
-            return new String(target);
-        } catch (Exception e) {
-            return Utils.printException(e);
-        }
-    }
-
-    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;
-         */
-
-        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");
-
-        char[] source = null;
-        if (methodBindingClass.isAssignableFrom(binding.getClass())) {
-            Object sourceMethod = method(binding, "sourceMethod");
-            if (sourceMethod == null) {
-                return null;
-            }
-            source = (char[]) method(method(field(sourceMethod, "compilationResult"), "getCompilationUnit"), "getContents");
-        } else if (referenceBindingClass.isAssignableFrom(binding.getClass())) {
-            source = (char[]) method(field(field(field(field(binding, "scope"), "referenceContext"), "compilationResult"), "compilationUnit"), "getContents");
-        }
-        return source;
-    }
-
-    @Override
-    public String getHeaderComment(ProcessingEnvironment env, Element type) {
-        try {
-            char[] source = getSource(type);
-            if (source == null) {
-                return null;
-            }
-            return parseHeader(new String(source));
-        } catch (Exception e) {
-            return Utils.printException(e);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JavaCCompiler.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.compiler;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.*;
-
-public class JavaCCompiler extends AbstractCompiler {
-
-    public static boolean isValidElement(Element currentElement) {
-        try {
-            Class<?> elementClass = Class.forName("com.sun.tools.javac.code.Symbol");
-            return elementClass.isAssignableFrom(currentElement.getClass());
-        } catch (ClassNotFoundException e) {
-            return false;
-        }
-    }
-
-    public List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type) {
-        return type.getEnclosedElements();
-    }
-
-    public List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) {
-        return environment.getElementUtils().getAllMembers(type);
-    }
-
-    private static final Class<?>[] getTreeAndTopLevelSignature = new Class[]{Element.class, AnnotationMirror.class, AnnotationValue.class};
-    private static final Class<?>[] getCharContentSignature = new Class[]{boolean.class};
-
-    @Override
-    public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
-        try {
-            /*
-             * if (false) { Pair<JCTree, JCCompilationUnit> treeAndTopLevel = ((JavacElements)
-             * env.getElementUtils()).getTreeAndTopLevel(method, null, null); JCBlock block =
-             * ((JCMethodDecl) treeAndTopLevel.fst).getBody(); int startPos = block.pos; int endPos
-             * = block.endpos; String methodBody =
-             * treeAndTopLevel.snd.getSourceFile().getCharContent(true).subSequence(startPos + 1,
-             * endPos).toString(); return methodBody; }
-             */
-
-            Object treeAndTopLevel = getTreeAndTopLevel(env, method);
-            Object block = method(field(treeAndTopLevel, "fst"), "getBody");
-            int startPos = (int) field(block, "pos");
-            int endPos = (int) field(block, "endpos");
-            return getContent(treeAndTopLevel).subSequence(startPos + 1, endPos).toString();
-        } catch (Exception e) {
-            return Utils.printException(e);
-        }
-    }
-
-    private static CharSequence getContent(Object treeAndTopLevel) throws Exception {
-        /*
-         * CharSequence content = treeAndTopLevel.snd.getSourceFile().getCharContent(true);
-         */
-        return (CharSequence) method(method(field(treeAndTopLevel, "snd"), "getSourceFile"), "getCharContent", getCharContentSignature, true);
-    }
-
-    private static Object getTreeAndTopLevel(ProcessingEnvironment env, Element element) throws Exception {
-        /*
-         * Pair<JCTree, JCCompilationUnit> treeAndTopLevel = ((JavacElements)
-         * env.getElementUtils()).getTreeAndTopLevel(method, null, null);
-         */
-        return method(method(env, "getElementUtils"), "getTreeAndTopLevel", getTreeAndTopLevelSignature, element, null, null);
-    }
-
-    @Override
-    public String getHeaderComment(ProcessingEnvironment env, Element type) {
-        try {
-            String content = getContent(getTreeAndTopLevel(env, type)).toString();
-            return parseHeader(content);
-        } catch (Exception e) {
-            return Utils.printException(e);
-        }
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractClassElementFactory.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+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.api.dsl.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public abstract class AbstractClassElementFactory<M> extends AbstractCodeElementFactory<M> {
+
+    @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();
+        TypeElement superClass = fromTypeMirror(clazz.getSuperclass());
+        ExecutableElement constructor = findConstructor(superClass);
+        if (constructor != null && constructor.getParameters().size() > 0) {
+            builder.startStatement();
+            builder.startSuperCall();
+            for (VariableElement parameter : constructor.getParameters()) {
+                method.addParameter(new CodeVariableElement(parameter.asType(), parameter.getSimpleName().toString()));
+                builder.string(parameter.getSimpleName().toString());
+            }
+            builder.end(); // super
+            builder.end(); // statement
+        }
+
+        for (VariableElement field : clazz.getFields()) {
+            if (field.getModifiers().contains(STATIC)) {
+                continue;
+            }
+            String fieldName = field.getSimpleName().toString();
+            method.addParameter(new CodeVariableElement(field.asType(), fieldName));
+            builder.startStatement();
+            builder.string("this.");
+            builder.string(fieldName);
+            builder.string(" = ");
+            if (isAssignable(field.asType(), getContext().getTruffleTypes().getNode())) {
+                builder.string("adoptChild(").string(fieldName).string(")");
+            } else {
+                builder.string(fieldName);
+            }
+            builder.end(); // statement
+        }
+
+        return method;
+    }
+
+    private static ExecutableElement findConstructor(TypeElement clazz) {
+        List<ExecutableElement> constructors = ElementFilter.constructorsIn(clazz.getEnclosedElements());
+        if (constructors.isEmpty()) {
+            return null;
+        } else {
+            return constructors.get(0);
+        }
+    }
+
+    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();
+
+        PackageElement pack = getContext().getEnvironment().getElementUtils().getPackageOf(templateType);
+        CodeTypeElement clazz = new CodeTypeElement(modifiers, enumType ? ElementKind.ENUM : ElementKind.CLASS, pack, simpleName);
+        TypeMirror resolvedSuperType = superType;
+        if (resolvedSuperType == null) {
+            resolvedSuperType = getContext().getType(Object.class);
+        }
+        clazz.setSuperClass(resolvedSuperType);
+
+        CodeAnnotationMirror generatedByAnnotation = new CodeAnnotationMirror((DeclaredType) getContext().getType(GeneratedBy.class));
+        generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("value"), new CodeAnnotationValue(templateType.asType()));
+        if (model.getTemplateMethodName() != null) {
+            generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("methodName"), new CodeAnnotationValue(model.getTemplateMethodName()));
+        }
+
+        clazz.addAnnotationMirror(generatedByAnnotation);
+
+        return clazz;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractCodeElementFactory.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public abstract class AbstractCodeElementFactory<M> {
+
+    protected final ProcessorContext context;
+    private M model;
+
+    private CodeElement<? super Element> element;
+
+    public AbstractCodeElementFactory() {
+        this.context = ProcessorContext.getInstance();
+    }
+
+    protected abstract CodeElement<?> create(M m);
+
+    @SuppressWarnings("unused")
+    protected void createChildren(M m) {
+    }
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    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);
+        }
+        return element;
+    }
+
+    @SuppressWarnings("rawtypes")
+    public CodeElement getElement() {
+        return element;
+    }
+
+    protected <MO, K extends Element> void add(AbstractCodeElementFactory<MO> factory, MO m) {
+        factory.process(this.element, m);
+    }
+
+    public ProcessorContext getContext() {
+        return context;
+    }
+
+    public M getModel() {
+        return model;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractCompilationUnitFactory.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public abstract class AbstractCompilationUnitFactory<M> extends AbstractCodeElementFactory<M> {
+
+    @Override
+    public final CodeCompilationUnit create(M m) {
+        return new CodeCompilationUnit();
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Override
+    public CodeCompilationUnit process(CodeElement parent, M m) {
+        return (CodeCompilationUnit) super.process(parent, m);
+    }
+
+    @Override
+    protected abstract void createChildren(M m);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,2935 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+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.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
+import com.oracle.truffle.dsl.processor.parser.*;
+import com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard;
+
+public class NodeCodeGenerator extends AbstractCompilationUnitFactory<NodeData> {
+
+    private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode";
+
+    private static final String EXECUTE_CHAINED = "executeChained0";
+    private static final String SPECIALIZE = "specialize0";
+    private static final String DSLSHARE_REWRITE = "rewrite";
+    private static final String DSLSHARE_FIND_ROOT = "findRoot";
+    private static final String DSLSHARE_REWRITE_TO_POLYMORHPIC = "rewriteToPolymorphic";
+    private static final String EXECUTE_UNINITIALIZED = "executeUninitialized0";
+    private static final String REWRITE = "rewrite0";
+    private static final String CREATE_INFO = "createInfo0";
+    private static final String CONTAINS_FALLBACK = "containsFallback";
+
+    private static final String FACTORY_METHOD_NAME = "create0";
+    private static final String EMPTY_CLASS_ARRAY = "EMPTY_CLASS_ARRAY";
+
+    private static final String METADATA_FIELD_NAME = "METADATA";
+
+    private TypeMirror getUnexpectedValueException() {
+        return getContext().getTruffleTypes().getUnexpectedValueException();
+    }
+
+    private static String factoryClassName(NodeData node) {
+        return node.getNodeId() + "Factory";
+    }
+
+    private static String nodeSpecializationClassName(SpecializationData specialization) {
+        String nodeid = resolveNodeId(specialization.getNode());
+        String name = ElementUtils.firstLetterUpperCase(nodeid);
+        name += ElementUtils.firstLetterUpperCase(specialization.getId());
+        name += "Node";
+        return name;
+    }
+
+    private static String nodePolymorphicClassName(NodeData node) {
+        return ElementUtils.firstLetterUpperCase(resolveNodeId(node)) + "PolymorphicNode";
+    }
+
+    private static String resolveNodeId(NodeData node) {
+        String nodeid = node.getNodeId();
+        if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
+            nodeid = nodeid.substring(0, nodeid.length() - 4);
+        }
+        return nodeid;
+    }
+
+    private static String valueNameEvaluated(Parameter targetParameter) {
+        return valueName(targetParameter) + "Evaluated";
+    }
+
+    private static String implicitTypeName(Parameter param) {
+        return param.getLocalName() + "ImplicitType";
+    }
+
+    private static String polymorphicTypeName(NodeExecutionData param) {
+        return param.getName() + "PolymorphicType";
+    }
+
+    private static String valueName(Parameter param) {
+        return param.getLocalName();
+    }
+
+    private static CodeTree createAccessChild(NodeExecutionData targetExecution, String thisReference) {
+        String reference = thisReference;
+        if (reference == null) {
+            reference = "this";
+        }
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        Element accessElement = targetExecution.getChild().getAccessElement();
+        if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) {
+            builder.string(reference).string(".").string(targetExecution.getChild().getName());
+        } else if (accessElement.getKind() == ElementKind.FIELD) {
+            builder.string(reference).string(".").string(accessElement.getSimpleName().toString());
+        } else {
+            throw new AssertionError();
+        }
+        if (targetExecution.isIndexed()) {
+            builder.string("[" + targetExecution.getIndex() + "]");
+        }
+        return builder.getRoot();
+    }
+
+    private static String castValueName(Parameter parameter) {
+        return valueName(parameter) + "Cast";
+    }
+
+    private void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean evaluated) {
+        if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
+            method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
+        }
+        for (Parameter parameter : specialization.getParameters()) {
+            ParameterSpec spec = parameter.getSpecification();
+            if (forceFrame && spec.getName().equals("frame")) {
+                continue;
+            }
+            if (spec.isLocal()) {
+                continue;
+            }
+
+            String name = valueName(parameter);
+            if (evaluated && spec.isSignature()) {
+                name = valueNameEvaluated(parameter);
+            }
+
+            method.addParameter(new CodeVariableElement(parameter.getType(), name));
+        }
+    }
+
+    private static void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame,
+                    Map<String, String> customNames) {
+        if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
+            builder.string("frameValue");
+        }
+        for (Parameter parameter : specialization.getParameters()) {
+            ParameterSpec spec = parameter.getSpecification();
+            if (forceFrame && spec.getName().equals("frame")) {
+                continue;
+            }
+
+            if (parameter.getSpecification().isLocal()) {
+                continue;
+            }
+
+            Parameter sourceParameter = source.findParameter(parameter.getLocalName());
+
+            if (customNames != null && customNames.containsKey(parameter.getLocalName())) {
+                builder.string(customNames.get(parameter.getLocalName()));
+            } else if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) {
+                builder.cast(parameter.getType(), CodeTreeBuilder.singleString("ex.getResult()"));
+            } else if (sourceParameter != null) {
+                builder.string(valueName(sourceParameter, parameter));
+            } else {
+                builder.string(valueName(parameter));
+            }
+        }
+    }
+
+    private static String valueName(Parameter sourceParameter, Parameter targetParameter) {
+        if (!sourceParameter.getSpecification().isSignature()) {
+            return valueName(targetParameter);
+        } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) {
+            if (sourceParameter.getTypeSystemType().needsCastTo(targetParameter.getTypeSystemType())) {
+                return castValueName(targetParameter);
+            }
+        }
+        return valueName(targetParameter);
+    }
+
+    private static CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName,
+                    String... customSignatureValueNames) {
+        CodeTreeBuilder builder = parent.create();
+
+        boolean castedValues = sourceMethod != targetMethod;
+
+        builder.startGroup();
+        ExecutableElement method = targetMethod.getMethod();
+        if (method == null) {
+            throw new UnsupportedOperationException();
+        }
+        TypeElement targetClass = ElementUtils.findNearestEnclosingType(method.getEnclosingElement());
+        NodeData node = (NodeData) targetMethod.getTemplate();
+
+        if (target == null) {
+            boolean accessible = targetMethod.canBeAccessedByInstanceOf(node.getNodeType());
+            if (accessible) {
+                if (builder.findMethod().getModifiers().contains(STATIC)) {
+                    if (method.getModifiers().contains(STATIC)) {
+                        builder.type(targetClass.asType());
+                    } else {
+                        builder.string(THIS_NODE_LOCAL_VAR_NAME);
+                    }
+                } else {
+                    if (targetMethod instanceof ExecutableTypeData) {
+                        builder.string("this");
+                    } else {
+                        builder.string("super");
+                    }
+                }
+            } else {
+                if (method.getModifiers().contains(STATIC)) {
+                    builder.type(targetClass.asType());
+                } else {
+                    Parameter firstParameter = null;
+                    for (Parameter searchParameter : targetMethod.getParameters()) {
+                        if (searchParameter.getSpecification().isSignature()) {
+                            firstParameter = searchParameter;
+                            break;
+                        }
+                    }
+                    if (firstParameter == null) {
+                        throw new AssertionError();
+                    }
+
+                    Parameter sourceParameter = sourceMethod.findParameter(firstParameter.getLocalName());
+
+                    if (castedValues && sourceParameter != null) {
+                        builder.string(valueName(sourceParameter, firstParameter));
+                    } else {
+                        builder.string(valueName(firstParameter));
+                    }
+                }
+            }
+            builder.string(".");
+        } else {
+            builder.tree(target);
+        }
+        builder.startCall(method.getSimpleName().toString());
+
+        int signatureIndex = 0;
+
+        for (Parameter targetParameter : targetMethod.getParameters()) {
+            Parameter valueParameter = null;
+            if (sourceMethod != null) {
+                valueParameter = sourceMethod.findParameter(targetParameter.getLocalName());
+            }
+            if (valueParameter == null) {
+                valueParameter = targetParameter;
+            }
+            TypeMirror targetType = targetParameter.getType();
+            TypeMirror valueType = null;
+            if (valueParameter != null) {
+                valueType = valueParameter.getType();
+            }
+
+            if (signatureIndex < customSignatureValueNames.length && targetParameter.getSpecification().isSignature()) {
+                builder.string(customSignatureValueNames[signatureIndex]);
+                signatureIndex++;
+            } else if (targetParameter.getSpecification().isLocal()) {
+                builder.startGroup();
+                if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) {
+                    builder.string(THIS_NODE_LOCAL_VAR_NAME).string(".");
+                } else {
+                    builder.string("this.");
+                }
+                builder.string(targetParameter.getSpecification().getName());
+                builder.end();
+            } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) {
+                builder.cast(targetParameter.getType(), CodeTreeBuilder.singleString("ex.getResult()"));
+            } else if (!ElementUtils.needsCastTo(valueType, targetType)) {
+                builder.startGroup();
+                builder.string(valueName(targetParameter));
+                builder.end();
+            } else {
+                builder.string(castValueName(targetParameter));
+            }
+        }
+
+        builder.end().end();
+
+        return builder.getRoot();
+    }
+
+    private static String baseClassName(NodeData node) {
+        String nodeid = resolveNodeId(node);
+        String name = ElementUtils.firstLetterUpperCase(nodeid);
+        name += "BaseNode";
+        return name;
+    }
+
+    private static CodeTree createCallTypeSystemMethod(CodeTreeBuilder parent, NodeData node, String methodName, CodeTree... args) {
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+        startCallTypeSystemMethod(builder, node.getTypeSystem(), methodName);
+        for (CodeTree arg : args) {
+            builder.tree(arg);
+        }
+        builder.end().end();
+        return builder.getRoot();
+    }
+
+    private static void startCallTypeSystemMethod(CodeTreeBuilder body, TypeSystemData typeSystem, String methodName) {
+        GeneratedTypeMirror typeMirror = new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()), TypeSystemCodeGenerator.typeName(typeSystem));
+        body.startGroup();
+        body.staticReference(typeMirror, TypeSystemCodeGenerator.singletonName(typeSystem));
+        body.string(".").startCall(methodName);
+    }
+
+    /**
+     * <pre>
+     * variant1 $condition != null
+     * 
+     * $type $name = defaultValue($type);
+     * if ($condition) {
+     *     $name = $value;
+     * }
+     * 
+     * variant2 $condition != null
+     * $type $name = $value;
+     * </pre>
+     *
+     * .
+     */
+    private static CodeTree createLazyAssignment(CodeTreeBuilder parent, String name, TypeMirror type, CodeTree condition, CodeTree value) {
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+        if (condition == null) {
+            builder.declaration(type, name, value);
+        } else {
+            builder.declaration(type, name, new CodeTreeBuilder(parent).defaultValue(type).getRoot());
+
+            builder.startIf().tree(condition).end();
+            builder.startBlock();
+            builder.startStatement();
+            builder.string(name);
+            builder.string(" = ");
+            builder.tree(value);
+            builder.end(); // statement
+            builder.end(); // block
+        }
+        return builder.getRoot();
+    }
+
+    private void emitEncounteredSynthetic(CodeTreeBuilder builder, TemplateMethod current) {
+        CodeTreeBuilder nodes = builder.create();
+        CodeTreeBuilder arguments = builder.create();
+        nodes.startCommaGroup();
+        arguments.startCommaGroup();
+        boolean empty = true;
+        for (Parameter parameter : current.getParameters()) {
+            NodeExecutionData executionData = parameter.getSpecification().getExecution();
+            if (executionData != null) {
+                if (executionData.isShortCircuit()) {
+                    nodes.nullLiteral();
+                    arguments.string(valueName(parameter.getPreviousParameter()));
+                }
+                nodes.tree(createAccessChild(executionData, "rootNode"));
+                arguments.string(valueName(parameter));
+                empty = false;
+            }
+        }
+        nodes.end();
+        arguments.end();
+        builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end();
+
+        builder.declaration(baseClassName(getModel()), "rootNode", builder.create().startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_FIND_ROOT).string("this").end());
+        builder.startThrow().startNew(getContext().getType(UnsupportedSpecializationException.class));
+        builder.string("rootNode");
+        builder.startNewArray(getContext().getTruffleTypes().getNodeArray(), null);
+        builder.tree(nodes.getRoot());
+        builder.end();
+        if (!empty) {
+            builder.tree(arguments.getRoot());
+        }
+        builder.end().end();
+    }
+
+    private static List<ExecutableElement> findUserConstructors(TypeMirror nodeType) {
+        List<ExecutableElement> constructors = new ArrayList<>();
+        for (ExecutableElement constructor : ElementFilter.constructorsIn(ElementUtils.fromTypeMirror(nodeType).getEnclosedElements())) {
+            if (constructor.getModifiers().contains(PRIVATE)) {
+                continue;
+            }
+            if (isCopyConstructor(constructor)) {
+                continue;
+            }
+            constructors.add(constructor);
+        }
+
+        if (constructors.isEmpty()) {
+            constructors.add(new CodeExecutableElement(null, ElementUtils.getSimpleName(nodeType)));
+        }
+
+        return constructors;
+    }
+
+    private static ExecutableElement findCopyConstructor(TypeMirror type) {
+        for (ExecutableElement constructor : ElementFilter.constructorsIn(ElementUtils.fromTypeMirror(type).getEnclosedElements())) {
+            if (constructor.getModifiers().contains(PRIVATE)) {
+                continue;
+            }
+            if (isCopyConstructor(constructor)) {
+                return constructor;
+            }
+        }
+
+        return null;
+    }
+
+    private static boolean isCopyConstructor(ExecutableElement element) {
+        if (element.getParameters().size() != 1) {
+            return false;
+        }
+        VariableElement var = element.getParameters().get(0);
+        TypeElement enclosingType = ElementUtils.findNearestEnclosingType(var);
+        if (ElementUtils.typeEquals(var.asType(), enclosingType.asType())) {
+            return true;
+        }
+        List<TypeElement> types = ElementUtils.getDirectSuperTypes(enclosingType);
+        for (TypeElement type : types) {
+            if (!(type instanceof CodeTypeElement)) {
+                // no copy constructors which are not generated types
+                return false;
+            }
+
+            if (ElementUtils.typeEquals(var.asType(), type.asType())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    protected void createChildren(NodeData node) {
+        List<CodeTypeElement> casts = new ArrayList<>(getElement().getEnclosedElements());
+        getElement().getEnclosedElements().clear();
+
+        Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>();
+        for (NodeData nodeChild : node.getEnclosingNodes()) {
+            NodeCodeGenerator generator = new NodeCodeGenerator();
+            childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements());
+        }
+
+        if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) {
+            NodeFactoryFactory factory = new NodeFactoryFactory(childTypes);
+            add(factory, node);
+            factory.getElement().getEnclosedElements().addAll(casts);
+        }
+    }
+
+    private static CodeTree createCastType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) {
+        if (targetType == null) {
+            return value;
+        } else if (sourceType != null && !sourceType.needsCastTo(targetType)) {
+            return value;
+        }
+
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        String targetMethodName;
+        if (expect) {
+            targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType);
+        } else {
+            targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
+        }
+        startCallTypeSystemMethod(builder, typeSystem, targetMethodName);
+        builder.tree(value);
+        builder.end().end();
+        return builder.getRoot();
+    }
+
+    private static CodeTree createExpectType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, CodeTree expression) {
+        return createCastType(typeSystem, sourceType, targetType, true, expression);
+    }
+
+    private CodeTree createDeoptimize(CodeTreeBuilder parent) {
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+        builder.startStatement();
+        builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end();
+        builder.end();
+        return builder.getRoot();
+    }
+
+    private class NodeFactoryFactory extends AbstractClassElementFactory<NodeData> {
+
+        private final Map<NodeData, List<TypeElement>> childTypes;
+        private CodeTypeElement generatedNode;
+
+        public NodeFactoryFactory(Map<NodeData, List<TypeElement>> childElements) {
+            this.childTypes = childElements;
+        }
+
+        @Override
+        protected CodeTypeElement create(NodeData node) {
+            Modifier visibility = ElementUtils.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);
+            return clazz;
+        }
+
+        @Override
+        protected void createChildren(NodeData node) {
+            CodeTypeElement clazz = getElement();
+
+            Modifier createVisibility = ElementUtils.getVisibility(clazz.getModifiers());
+
+            if (node.needsFactory()) {
+                NodeBaseFactory factory = new NodeBaseFactory();
+                add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization());
+                generatedNode = factory.getElement();
+
+                createFactoryMethods(node, clazz, createVisibility);
+
+                for (SpecializationData specialization : node.getSpecializations()) {
+                    if (!specialization.isReachable() || specialization.isGeneric()) {
+                        continue;
+                    }
+
+                    if (specialization.isPolymorphic() && node.isPolymorphic(context)) {
+                        PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(generatedNode);
+                        add(polymorphicFactory, specialization);
+                        continue;
+                    }
+
+                    add(new SpecializedNodeFactory(generatedNode), specialization);
+                }
+
+                TypeMirror nodeFactory = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(getContext().getTruffleTypes().getNodeFactoryBase()), node.getNodeType());
+                clazz.setSuperClass(nodeFactory);
+                clazz.add(createNodeFactoryConstructor(node));
+                clazz.add(createCreateNodeMethod(node));
+// clazz.add(createGetNodeClassMethod(node));
+// clazz.add(createGetNodeSignaturesMethod());
+// clazz.add(createGetChildrenSignatureMethod(node));
+                clazz.add(createGetInstanceMethod(node, createVisibility));
+                clazz.add(createInstanceConstant(node, clazz.asType()));
+            }
+
+            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 = ElementUtils.getVisibility(type.getModifiers());
+                    typeModifiers.clear();
+                    if (visibility != null) {
+                        typeModifiers.add(visibility);
+                    }
+
+                    typeModifiers.add(Modifier.STATIC);
+                    typeModifiers.add(Modifier.FINAL);
+                    clazz.add(type);
+                }
+            }
+
+            List<NodeData> children = node.getNodeDeclaringChildren();
+            if (node.getDeclaringNode() == null && children.size() > 0) {
+                clazz.add(createGetFactories(node));
+            }
+
+        }
+
+        private Element createNodeFactoryConstructor(NodeData node) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), null, factoryClassName(node));
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startStatement();
+            builder.startCall("super");
+
+            // node type
+            builder.typeLiteral(node.getNodeType());
+
+            // execution signature
+            builder.startGroup();
+            if (node.getChildExecutions().isEmpty()) {
+                builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
+            } else {
+                builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null);
+                for (NodeExecutionData execution : node.getChildExecutions()) {
+                    builder.typeLiteral(execution.getNodeType());
+                }
+                builder.end();
+            }
+            builder.end();
+
+            // node signatures
+            builder.startGroup();
+            builder.startNewArray(new ArrayCodeTypeMirror(new ArrayCodeTypeMirror(context.getType(Class.class))), null);
+            List<ExecutableElement> constructors = findUserConstructors(generatedNode.asType());
+            for (ExecutableElement constructor : constructors) {
+                builder.startGroup();
+                if (constructor.getParameters().isEmpty()) {
+                    builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
+                } else {
+                    builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null);
+                    for (VariableElement var : constructor.getParameters()) {
+                        builder.typeLiteral(var.asType());
+                    }
+                    builder.end();
+                }
+                builder.end();
+            }
+            builder.end();
+            builder.end();
+
+            builder.end().end().end();
+            return method;
+        }
+
+        private CodeExecutableElement createCreateNodeMethod(NodeData node) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode");
+            CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments");
+            method.setVarArgs(true);
+            method.addParameter(arguments);
+
+            CodeTreeBuilder builder = method.createBuilder();
+            List<ExecutableElement> signatures = findUserConstructors(generatedNode.asType());
+            boolean ifStarted = false;
+
+            for (ExecutableElement element : signatures) {
+                ifStarted = builder.startIf(ifStarted);
+                builder.string("arguments.length == " + element.getParameters().size());
+
+                int index = 0;
+                for (VariableElement param : element.getParameters()) {
+                    if (ElementUtils.isObject(param.asType())) {
+                        continue;
+                    }
+                    builder.string(" && ");
+                    if (!param.asType().getKind().isPrimitive()) {
+                        builder.string("(arguments[" + index + "] == null || ");
+                    }
+                    builder.string("arguments[" + index + "] instanceof ");
+                    builder.type(ElementUtils.boxType(getContext(), param.asType()));
+                    if (!param.asType().getKind().isPrimitive()) {
+                        builder.string(")");
+                    }
+                    index++;
+                }
+                builder.end();
+                builder.startBlock();
+
+                builder.startReturn().startCall("create");
+                index = 0;
+                for (VariableElement param : element.getParameters()) {
+                    builder.startGroup();
+                    if (!ElementUtils.isObject(param.asType())) {
+                        builder.string("(").type(param.asType()).string(") ");
+                    }
+                    builder.string("arguments[").string(String.valueOf(index)).string("]");
+                    builder.end();
+                    index++;
+                }
+                builder.end().end();
+
+                builder.end(); // block
+            }
+
+            builder.startElseBlock();
+            builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class));
+            builder.doubleQuote("Invalid create signature.");
+            builder.end().end();
+            builder.end(); // else block
+            return method;
+        }
+
+        private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) {
+            TypeElement nodeFactoryType = ElementUtils.fromTypeMirror(getContext().getType(NodeFactory.class));
+            TypeMirror returnType = ElementUtils.getDeclaredType(nodeFactoryType, node.getNodeType());
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance");
+            if (visibility != null) {
+                method.getModifiers().add(visibility);
+            }
+            method.getModifiers().add(Modifier.STATIC);
+
+            String varName = instanceVarName(node);
+
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startIf();
+            builder.string(varName).string(" == null");
+            builder.end().startBlock();
+
+            builder.startStatement();
+            builder.string(varName);
+            builder.string(" = ");
+            builder.startNew(factoryClassName(node)).end();
+            builder.end();
+
+            builder.end();
+            builder.startReturn().string(varName).end();
+            return method;
+        }
+
+        private String instanceVarName(NodeData node) {
+            if (node.getDeclaringNode() != null) {
+                return ElementUtils.firstLetterLowerCase(factoryClassName(node)) + "Instance";
+            } else {
+                return "instance";
+            }
+        }
+
+        private CodeVariableElement createInstanceConstant(NodeData node, TypeMirror factoryType) {
+            String varName = instanceVarName(node);
+            CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName);
+            var.getModifiers().add(Modifier.PRIVATE);
+            var.getModifiers().add(Modifier.STATIC);
+            return var;
+        }
+
+        private ExecutableElement createGetFactories(NodeData node) {
+            List<NodeData> children = node.getNodeDeclaringChildren();
+            if (node.needsFactory()) {
+                children.add(node);
+            }
+
+            List<TypeMirror> nodeTypesList = new ArrayList<>();
+            TypeMirror prev = null;
+            boolean allSame = true;
+            for (NodeData child : children) {
+                nodeTypesList.add(child.getNodeType());
+                if (prev != null && !ElementUtils.typeEquals(child.getNodeType(), prev)) {
+                    allSame = false;
+                }
+                prev = child.getNodeType();
+            }
+            TypeMirror commonNodeSuperType = ElementUtils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()]));
+
+            Types types = getContext().getEnvironment().getTypeUtils();
+            TypeMirror factoryType = getContext().getType(NodeFactory.class);
+            TypeMirror baseType;
+            if (allSame) {
+                baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), commonNodeSuperType);
+            } else {
+                baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null));
+            }
+            TypeMirror listType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(getContext().getType(List.class)), baseType);
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories");
+
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startReturn();
+            builder.startStaticCall(getContext().getType(Arrays.class), "asList");
+
+            for (NodeData child : children) {
+                builder.startGroup();
+                NodeData childNode = child;
+                List<NodeData> factories = new ArrayList<>();
+                while (childNode.getDeclaringNode() != null) {
+                    factories.add(childNode);
+                    childNode = childNode.getDeclaringNode();
+                }
+                Collections.reverse(factories);
+                for (NodeData nodeData : factories) {
+                    builder.string(factoryClassName(nodeData)).string(".");
+                }
+                builder.string("getInstance()");
+                builder.end();
+            }
+            builder.end();
+            builder.end();
+            return method;
+        }
+
+        private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) {
+            List<ExecutableElement> constructors = findUserConstructors(generatedNode.asType());
+            for (ExecutableElement constructor : constructors) {
+                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().isEmpty()) {
+                body.nullLiteral();
+            } else {
+                body.startCall(nodeSpecializationClassName(node.getSpecializations().get(0)), FACTORY_METHOD_NAME);
+                for (VariableElement var : method.getParameters()) {
+                    body.string(var.getSimpleName().toString());
+                }
+                body.end();
+            }
+            body.end();
+            return method;
+        }
+
+    }
+
+    private class NodeBaseFactory extends AbstractClassElementFactory<SpecializationData> {
+
+        @Override
+        protected CodeTypeElement create(SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false);
+            clazz.getImplements().add(context.getTruffleTypes().getDslNode());
+
+            for (NodeChildData child : node.getChildren()) {
+                clazz.add(createChildField(child));
+
+                if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) {
+                    ExecutableElement getter = (ExecutableElement) child.getAccessElement();
+                    CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter);
+                    method.getModifiers().remove(Modifier.ABSTRACT);
+                    CodeTreeBuilder builder = method.createBuilder();
+                    builder.startReturn().string("this.").string(child.getName()).end();
+                    clazz.add(method);
+                }
+            }
+
+            for (NodeFieldData field : node.getFields()) {
+                if (!field.isGenerated()) {
+                    continue;
+                }
+
+                clazz.add(new CodeVariableElement(modifiers(PROTECTED, FINAL), field.getType(), field.getName()));
+                if (field.getGetter() != null && field.getGetter().getModifiers().contains(Modifier.ABSTRACT)) {
+                    CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), field.getGetter());
+                    method.getModifiers().remove(Modifier.ABSTRACT);
+                    method.createBuilder().startReturn().string("this.").string(field.getName()).end();
+                    clazz.add(method);
+                }
+            }
+
+            for (String assumption : node.getAssumptions()) {
+                clazz.add(createAssumptionField(assumption));
+            }
+
+            createConstructors(node, clazz);
+
+            return clazz;
+        }
+
+        @Override
+        protected void createChildren(SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            CodeTypeElement clazz = getElement();
+
+            SpecializationGroup rootGroup = createSpecializationGroups(node);
+
+            if (node.needsRewrites(context)) {
+                if (node.isPolymorphic(context)) {
+
+                    CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0");
+                    var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation()));
+                    clazz.add(var);
+
+                    CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization());
+                    clazz.add(genericCachedExecute);
+
+                }
+
+                for (CodeExecutableElement method : createImplicitChildrenAccessors()) {
+                    clazz.add(method);
+                }
+                clazz.add(createInfoMessage(node));
+                clazz.add(createMonomorphicRewrite());
+                clazz.add(createCreateSpecializationMethod(node, rootGroup));
+            }
+
+            clazz.add(createAdoptChildren0());
+            clazz.add(createGetMetadata0(true));
+            clazz.add(createUpdateTypes0());
+            clazz.add(createGetNext());
+        }
+
+        private Element createGetNext() {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(Node.class), "getNext0");
+            CodeTreeBuilder builder = method.createBuilder();
+            NodeData node = getModel().getNode();
+
+            if (node.isPolymorphic(context)) {
+                builder.startReturn().string("next0").end();
+            } else {
+                builder.returnNull();
+            }
+
+            return method;
+        }
+
+        protected final CodeExecutableElement createUpdateTypes0() {
+            ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class));
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(void.class), "updateTypes0");
+            method.getParameters().add(new CodeVariableElement(classArray, "types"));
+
+            if (getModel().isPolymorphic()) {
+                CodeTreeBuilder builder = method.createBuilder();
+
+                int index = 0;
+                for (NodeExecutionData execution : getModel().getNode().getChildExecutions()) {
+                    String fieldName = polymorphicTypeName(execution);
+
+                    builder.startStatement();
+                    builder.string(fieldName).string(" = ").string("types[").string(String.valueOf(index)).string("]");
+                    builder.end();
+                    index++;
+                }
+            }
+
+            return method;
+        }
+
+        protected final CodeExecutableElement createGetMetadata0(boolean empty) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getTruffleTypes().getDslMetadata(), "getMetadata0");
+            if (empty) {
+                method.createBuilder().startReturn().staticReference(context.getTruffleTypes().getDslMetadata(), "NONE").end();
+            } else {
+                method.createBuilder().startReturn().string(METADATA_FIELD_NAME).end();
+            }
+            return method;
+        }
+
+        private CodeExecutableElement createAdoptChildren0() {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(void.class), "adoptChildren0");
+            method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "other"));
+            method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "newNext"));
+            NodeData node = getModel().getNode();
+            CodeTreeBuilder builder = method.createBuilder();
+            List<NodeExecutionData> executions = node.getChildExecutions();
+
+            if (executions.size() > 0) {
+                builder.startIf().string("other == null").end().startBlock();
+                for (NodeExecutionData execution : executions) {
+                    builder.startStatement().tree(createAccessChild(execution, "this")).string(" = null").end();
+                }
+                builder.end().startElseBlock();
+
+                String access;
+                if (executions.size() > 1) {
+                    builder.declaration(baseClassName(node), "otherCast", builder.create().cast(baseClassName(node)).string("other"));
+                    access = "otherCast";
+                } else {
+                    assert executions.size() == 1;
+                    access = "((" + baseClassName(node) + ") other)";
+                }
+                for (NodeExecutionData execution : executions) {
+                    builder.startStatement().tree(createAccessChild(execution, "this")).string(" = ").tree(createAccessChild(execution, access)).end();
+                }
+
+                builder.end();
+            }
+
+            if (getModel().getNode().isPolymorphic(context)) {
+                builder.startIf().string("newNext == null").end().startBlock();
+                builder.statement("this.next0 = null");
+                builder.end().startElseBlock();
+                builder.statement("this.next0 = (" + baseClassName(getModel().getNode()) + ") newNext");
+                builder.end();
+            }
+
+            return method;
+        }
+
+        private List<CodeExecutableElement> createImplicitChildrenAccessors() {
+            NodeData node = getModel().getNode();
+            List<Set<TypeData>> prototype = Collections.nCopies(node.getGenericSpecialization().getParameters().size(), null);
+            List<Set<TypeData>> expectTypes = new ArrayList<>(prototype);
+
+            for (ExecutableTypeData executableType : node.getExecutableTypes()) {
+                for (int i = 0; i < executableType.getEvaluatedCount(); i++) {
+                    Parameter parameter = executableType.getSignatureParameter(i);
+                    if (i >= expectTypes.size()) {
+                        break;
+                    }
+                    Set<TypeData> types = expectTypes.get(i);
+                    if (types == null) {
+                        types = new TreeSet<>();
+                        expectTypes.set(i, types);
+                    }
+                    types.add(parameter.getTypeSystemType());
+                }
+            }
+
+            List<CodeExecutableElement> methods = new ArrayList<>();
+            List<Set<TypeData>> visitedList = new ArrayList<>(prototype);
+            for (SpecializationData spec : node.getSpecializations()) {
+                int signatureIndex = -1;
+                for (Parameter param : spec.getParameters()) {
+                    if (!param.getSpecification().isSignature()) {
+                        continue;
+                    }
+                    signatureIndex++;
+                    Set<TypeData> visitedTypeData = visitedList.get(signatureIndex);
+                    if (visitedTypeData == null) {
+                        visitedTypeData = new TreeSet<>();
+                        visitedList.set(signatureIndex, visitedTypeData);
+                    }
+
+                    if (visitedTypeData.contains(param.getTypeSystemType())) {
+                        continue;
+                    }
+                    visitedTypeData.add(param.getTypeSystemType());
+
+                    Set<TypeData> expect = expectTypes.get(signatureIndex);
+                    if (expect == null) {
+                        expect = Collections.emptySet();
+                    }
+
+                    methods.addAll(createExecuteChilds(param, expect));
+                }
+            }
+            return methods;
+        }
+
+        private CodeTree truffleBooleanOption(CodeTreeBuilder parent, String name) {
+            CodeTreeBuilder builder = parent.create();
+            builder.staticReference(getContext().getTruffleTypes().getTruffleOptions(), name);
+            return builder.getRoot();
+        }
+
+        private Element createInfoMessage(NodeData node) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), getContext().getType(String.class), CREATE_INFO);
+            method.addParameter(new CodeVariableElement(getContext().getType(String.class), "message"));
+            addInternalValueParameters(method, node.getGenericSpecialization(), false, false);
+
+            CodeTreeBuilder builder = method.createBuilder();
+
+            builder.startIf().tree(truffleBooleanOption(builder, TruffleTypes.OPTION_DETAILED_REWRITE_REASONS)).end();
+            builder.startBlock();
+
+            builder.startStatement().string("StringBuilder builder = new StringBuilder(message)").end();
+            builder.startStatement().startCall("builder", "append").doubleQuote(" (").end().end();
+
+            String sep = null;
+            for (Parameter parameter : node.getGenericSpecialization().getSignatureParameters()) {
+                builder.startStatement();
+                builder.string("builder");
+                if (sep != null) {
+                    builder.startCall(".append").doubleQuote(sep).end();
+                }
+                builder.startCall(".append").doubleQuote(parameter.getLocalName()).end();
+                builder.startCall(".append").doubleQuote(" = ").end();
+                builder.startCall(".append").string(parameter.getLocalName()).end();
+                builder.end();
+
+                if (!ElementUtils.isPrimitive(parameter.getType())) {
+                    builder.startIf().string(parameter.getLocalName() + " != null").end();
+                    builder.startBlock();
+                }
+                builder.startStatement();
+                if (ElementUtils.isPrimitive(parameter.getType())) {
+                    builder.startCall("builder.append").doubleQuote(" (" + ElementUtils.getSimpleName(parameter.getType()) + ")").end();
+                } else {
+                    builder.startCall("builder.append").doubleQuote(" (").end();
+                    builder.startCall(".append").string(parameter.getLocalName() + ".getClass().getSimpleName()").end();
+                    builder.startCall(".append").doubleQuote(")").end();
+                }
+                builder.end();
+                if (!ElementUtils.isPrimitive(parameter.getType())) {
+                    builder.end();
+                }
+
+                sep = ", ";
+            }
+
+            builder.startStatement().startCall("builder", "append").doubleQuote(")").end().end();
+            builder.startReturn().string("builder.toString()").end();
+
+            builder.end();
+            builder.startElseBlock();
+            builder.startReturn().string("message").end();
+            builder.end();
+
+            return method;
+        }
+
+        private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) {
+            CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_CHAINED);
+            addInternalValueParameters(cachedExecute, polymorph, true, false);
+
+            ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0);
+            boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext());
+            if (sourceThrowsUnexpected && sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) {
+                sourceThrowsUnexpected = false;
+            }
+            if (sourceThrowsUnexpected) {
+                cachedExecute.getThrownTypes().add(getContext().getType(UnexpectedResultException.class));
+            }
+            return cachedExecute;
+
+        }
+
+        private void createConstructors(NodeData node, CodeTypeElement clazz) {
+            List<ExecutableElement> constructors = findUserConstructors(node.getNodeType());
+            ExecutableElement sourceSectionConstructor = null;
+            if (constructors.isEmpty()) {
+                clazz.add(createUserConstructor(clazz, null));
+            } else {
+                for (ExecutableElement constructor : constructors) {
+                    clazz.add(createUserConstructor(clazz, constructor));
+                    if (NodeParser.isSourceSectionConstructor(context, constructor)) {
+                        sourceSectionConstructor = constructor;
+                    }
+                }
+            }
+            if (node.needsRewrites(getContext())) {
+                ExecutableElement copyConstructor = findCopyConstructor(node.getNodeType());
+                clazz.add(createCopyConstructor(clazz, copyConstructor, sourceSectionConstructor));
+            }
+        }
+
+        private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
+            CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
+            CodeTreeBuilder builder = method.createBuilder();
+
+            NodeData node = getModel().getNode();
+
+            if (superConstructor != null) {
+                for (VariableElement param : superConstructor.getParameters()) {
+                    method.getParameters().add(CodeVariableElement.clone(param));
+                }
+            }
+
+            if (superConstructor != null) {
+                builder.startStatement().startSuperCall();
+                for (VariableElement param : superConstructor.getParameters()) {
+                    builder.string(param.getSimpleName().toString());
+                }
+                builder.end().end();
+            }
+
+            for (VariableElement var : type.getFields()) {
+                if (var.getModifiers().contains(STATIC)) {
+                    continue;
+                }
+                NodeChildData child = node.findChild(var.getSimpleName().toString());
+
+                if (child != null) {
+                    method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName()));
+                } else {
+                    method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
+                }
+
+                builder.startStatement();
+                String fieldName = var.getSimpleName().toString();
+
+                CodeTree init = createStaticCast(builder, child, fieldName);
+
+                builder.string("this.").string(fieldName).string(" = ").tree(init);
+                builder.end();
+            }
+            return method;
+        }
+
+        private CodeTree createStaticCast(CodeTreeBuilder parent, NodeChildData child, String fieldName) {
+            NodeData parentNode = getModel().getNode();
+            if (child != null) {
+                CreateCastData createCast = parentNode.findCast(child.getName());
+                if (createCast != null) {
+                    return createTemplateMethodCall(parent, null, parentNode.getGenericSpecialization(), createCast, null, fieldName);
+                }
+            }
+            return CodeTreeBuilder.singleString(fieldName);
+        }
+
+        private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor, ExecutableElement sourceSectionConstructor) {
+            CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
+            CodeTreeBuilder builder = method.createBuilder();
+            method.getParameters().add(new CodeVariableElement(type.asType(), "copy"));
+
+            if (superConstructor != null) {
+                builder.startStatement().startSuperCall().string("copy").end().end();
+            } else if (sourceSectionConstructor != null) {
+                builder.startStatement().startSuperCall().string("copy.getSourceSection()").end().end();
+            }
+
+            for (VariableElement var : type.getFields()) {
+                if (var.getModifiers().contains(STATIC) || !var.getModifiers().contains(FINAL)) {
+                    continue;
+                }
+                final String varName = var.getSimpleName().toString();
+                final TypeMirror varType = var.asType();
+                if (ElementUtils.isAssignable(varType, getContext().getTruffleTypes().getNodeArray())) {
+                    CodeTree size = builder.create().string("copy.", varName, ".length").getRoot();
+                    builder.startStatement().string("this.").string(varName).string(" = ").startNewArray((ArrayType) varType, size).end().end();
+                } else {
+                    builder.startStatement().string("this.", varName, " = copy.", varName).end();
+                }
+            }
+
+            return method;
+        }
+
+        private CodeVariableElement createAssumptionField(String assumption) {
+            CodeVariableElement var = new CodeVariableElement(getContext().getTruffleTypes().getAssumption(), assumption);
+            var.getModifiers().add(Modifier.FINAL);
+            return var;
+        }
+
+        private CodeVariableElement createChildField(NodeChildData child) {
+            TypeMirror type = child.getNodeType();
+            CodeVariableElement var = new CodeVariableElement(type, child.getName());
+            var.getModifiers().add(Modifier.PROTECTED);
+
+            DeclaredType annotationType;
+            if (child.getCardinality() == Cardinality.MANY) {
+                var.getModifiers().add(Modifier.FINAL);
+                annotationType = getContext().getTruffleTypes().getChildrenAnnotation();
+            } else {
+                annotationType = getContext().getTruffleTypes().getChildAnnotation();
+            }
+
+            var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType));
+            return var;
+        }
+
+        private SpecializationGroup createSpecializationGroups(final NodeData node) {
+            List<SpecializationData> specializations = node.getSpecializations();
+            List<SpecializationData> filteredSpecializations = new ArrayList<>();
+            for (SpecializationData current : specializations) {
+                if (current.isUninitialized() || current.isPolymorphic() || !current.isReachable()) {
+                    continue;
+                }
+                filteredSpecializations.add(current);
+            }
+
+            return SpecializationGroup.create(filteredSpecializations);
+        }
+
+        protected final CodeExecutableElement createExecuteUninitialized() {
+            NodeData node = getModel().getNode();
+            SpecializationData generic = node.getGenericSpecialization();
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), generic.getReturnType().getType(), EXECUTE_UNINITIALIZED);
+            addInternalValueParameters(method, generic, true, false);
+            CodeTreeBuilder builder = method.createBuilder();
+
+            CodeTreeBuilder createSpecializationCall = builder.create();
+            createSpecializationCall.startCall(SPECIALIZE);
+            addInternalValueParameterNames(createSpecializationCall, generic, generic, null, node.needsFrame(getContext()), null);
+            createSpecializationCall.end();
+            builder.declaration(baseClassName(node), "newNode", createSpecializationCall);
+
+            if (generic.isReachable()) {
+                builder.startIf().string("newNode == null").end().startBlock();
+
+                builder.startIf().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "inInterpreter").end().end().startBlock();
+                builder.statement("containsFallback = true");
+                builder.end();
+                builder.tree(createGenericInvoke(builder, generic, generic));
+                builder.end();
+                builder.startElseBlock();
+                builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
+            }
+
+            builder.startReturn();
+            builder.startStaticCall(context.getTruffleTypes().getDslShare(), "rewriteUninitialized").string("this").string("newNode").end();
+            builder.string(".").startCall(EXECUTE_CHAINED);
+            addInternalValueParameterNames(builder, generic, generic, null, true, null);
+            builder.end();
+            builder.end();
+
+            if (generic.isReachable()) {
+                builder.end();
+            }
+
+            return method;
+        }
+
+        private CodeTree createInfoCall(CodeTreeBuilder parent, SpecializationData specialization, String reason) {
+            CodeTreeBuilder builder = parent.create();
+            builder.startCall(CREATE_INFO).string(reason);
+            addInternalValueParameterNames(builder, specialization, specialization, null, false, null);
+            builder.end();
+            return builder.getRoot();
+        }
+
+        private CodeExecutableElement createMonomorphicRewrite() {
+            NodeData node = getModel().getNode();
+
+            SpecializationData generic = node.getGenericSpecialization();
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), generic.getReturnType().getType(), REWRITE);
+            addInternalValueParameters(method, generic, true, false);
+            method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
+
+            CodeTreeBuilder builder = method.createBuilder();
+
+            builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end().end();
+            String baseClassName = baseClassName(getModel().getNode());
+            CodeTreeBuilder createSpecializationCall = builder.create();
+            createSpecializationCall.startCall(SPECIALIZE);
+            addInternalValueParameterNames(createSpecializationCall, generic, generic, null, node.needsFrame(getContext()), null);
+            createSpecializationCall.end();
+            builder.declaration(baseClassName, "newNode", createSpecializationCall);
+
+            builder.startIf().string("newNode == null").end().startBlock();
+            builder.startStatement();
+            String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization());
+            builder.string("newNode = ").startNew(uninitializedName).string("this").end();
+            builder.end();
+            if (node.isFallbackReachable()) {
+                builder.startStatement().string("((", uninitializedName, ") newNode).containsFallback = true").end();
+            }
+            builder.end();
+
+            builder.startStatement();
+            builder.type(getContext().getType(String.class)).string(" message = ").tree(createInfoCall(builder, generic, "reason"));
+            builder.end();
+
+            builder.declaration(baseClassName, "returnNode",
+                            builder.create().startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_REWRITE).string("this").string("newNode").string("message").end().getRoot());
+            builder.startIf().string("returnNode == null").end().startBlock();
+            builder.tree(createRewritePolymorphic(builder, node, "this"));
+            builder.end();
+
+            builder.startReturn();
+            builder.startCall("returnNode", EXECUTE_CHAINED);
+            addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, null);
+            builder.end();
+            builder.end();
+
+            return method;
+        }
+
+        private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node, String currentNode) {
+            String polyClassName = nodePolymorphicClassName(node);
+            CodeTreeBuilder builder = parent.create();
+
+            builder.startStatement().string("returnNode = ");
+            builder.startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_REWRITE_TO_POLYMORHPIC);
+            builder.string("this");
+            builder.tree(builder.create().startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string(currentNode).end().getRoot());
+            builder.tree(builder.create().startNew(polyClassName).string(currentNode).end().getRoot());
+            builder.startGroup().cast(baseClassName(node)).startCall("copy").end().end();
+            builder.string("newNode");
+            builder.string("message");
+            builder.end();
+            builder.end();
+
+            return builder.getRoot();
+        }
+
+        private CodeExecutableElement createCreateSpecializationMethod(NodeData node, SpecializationGroup group) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), new GeneratedTypeMirror(ElementUtils.getPackageName(node.getTemplateType()), baseClassName(node)),
+                            SPECIALIZE);
+            if (!node.needsFrame(getContext())) {
+                method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath()));
+            }
+
+            addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(getContext()), false);
+            final CodeTreeBuilder builder = method.createBuilder();
+            builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, new CodeBlock<SpecializationData>() {
+
+                public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
+                    return createCreateSpecializationMethodBody0(builder, current);
+                }
+            }, null, false, true, false, true));
+
+            emitUnreachableSpecializations(builder, node);
+
+            return method;
+        }
+
+        protected CodeTree createCreateSpecializationMethodBody0(CodeTreeBuilder parent, SpecializationData current) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            if (current.isGeneric()) {
+                builder.startReturn().nullLiteral().end();
+            } else {
+                String className = nodeSpecializationClassName(current);
+                if (!current.getExcludedBy().isEmpty()) {
+                    builder.startIf().string("!").startStaticCall(context.getTruffleTypes().getDslShare(), "isExcluded");
+                    builder.string("this").string(nodeSpecializationClassName(current), ".", METADATA_FIELD_NAME).end().end();
+                    builder.startBlock();
+                }
+
+                if (current.getNode().getGenericSpecialization().isReachable()) {
+                    builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
+                }
+                builder.startReturn();
+                builder.cast(baseClassName(getModel().getNode()));
+                builder.startGroup().startCall(className, FACTORY_METHOD_NAME).string("this");
+                for (Parameter param : current.getSignatureParameters()) {
+                    NodeChildData child = param.getSpecification().getExecution().getChild();
+                    List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
+                    if (types.size() > 1) {
+                        builder.string(implicitTypeName(param));
+                    }
+                }
+                builder.end().end();
+                builder.end();
+
+                if (!current.getExcludedBy().isEmpty()) {
+                    builder.end();
+                }
+            }
+            return builder.getRoot();
+
+        }
+
+        private void emitUnreachableSpecializations(final CodeTreeBuilder builder, NodeData node) {
+            for (SpecializationData current : node.getSpecializations()) {
+                if (current.isReachable()) {
+                    continue;
+                }
+                builder.string("// unreachable ").string(current.getId()).newLine();
+            }
+        }
+
+        protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final CodeBlock<SpecializationData> guardedblock,
+                        final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions, final boolean typedCasts, final boolean castForGuardsOnly) {
+            return guard(outerParent, source, group, new CodeBlock<Integer>() {
+
+                public CodeTree create(CodeTreeBuilder parent, Integer ifCount) {
+                    CodeTreeBuilder builder = parent.create();
+
+                    if (group.getSpecialization() != null) {
+                        builder.tree(guardedblock.create(builder, group.getSpecialization()));
+
+                        assert group.getChildren().isEmpty() : "missed a specialization";
+
+                    } else {
+                        for (SpecializationGroup childGroup : group.getChildren()) {
+                            builder.tree(createExecuteTree(builder, source, childGroup, guardedblock, null, false, emitAssumptions, typedCasts, castForGuardsOnly));
+                        }
+                    }
+
+                    return builder.getRoot();
+                }
+            }, elseBlock, forceElse, emitAssumptions, typedCasts, castForGuardsOnly);
+        }
+
+        private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, CodeBlock<Integer> bodyBlock, CodeTree elseBlock, boolean forceElse,
+                        boolean emitAssumptions, boolean typedCasts, boolean castForGuardsOnly) {
+            CodeTreeBuilder builder = parent.create();
+
+            int ifCount = emitGuards(builder, source, group, emitAssumptions, typedCasts, castForGuardsOnly);
+
+            if (isReachableGroup(group, ifCount)) {
+                builder.tree(bodyBlock.create(builder, ifCount));
+            }
+
+            builder.end(ifCount);
+
+            if (elseBlock != null) {
+                if (ifCount > 0 || forceElse) {
+                    builder.tree(elseBlock);
+                }
+            }
+
+            return builder.getRoot();
+        }
+
+        private boolean isReachableGroup(SpecializationGroup group, int ifCount) {
+            if (ifCount != 0) {
+                return true;
+            }
+            SpecializationGroup previous = group.getPreviousGroup();
+            if (previous == null || previous.findElseConnectableGuards().isEmpty()) {
+                return true;
+            }
+
+            /*
+             * Hacky else case. In this case the specialization is not reachable due to previous
+             * else branch. This is only true if the minimum state is not checked.
+             */
+            if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && previous.getAssumptions().isEmpty() &&
+                            (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) {
+                return false;
+            }
+
+            return true;
+        }
+
+        private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean emitAssumptions, boolean typedCasts, boolean castForGuardsOnly) {
+            NodeData node = source.getNode();
+
+            CodeTreeBuilder guardsBuilder = builder.create();
+            CodeTreeBuilder castBuilder = builder.create();
+            CodeTreeBuilder guardsCastBuilder = builder.create();
+
+            String guardsAnd = "";
+            String guardsCastAnd = "";
+
+            if (emitAssumptions) {
+                for (String assumption : group.getAssumptions()) {
+                    guardsBuilder.string(guardsAnd);
+                    guardsBuilder.string("this");
+                    guardsBuilder.string(".").string(assumption).string(".isValid()");
+                    guardsAnd = " && ";
+                }
+            }
+
+            for (TypeGuard typeGuard : group.getTypeGuards()) {
+                Parameter valueParam = source.getSignatureParameter(typeGuard.getSignatureIndex());
+
+                if (valueParam == null) {
+                    /*
+                     * If used inside a execute evaluated method then the value param may not exist.
+                     * In that case we assume that the value is executed generic or of the current
+                     * specialization.
+                     */
+                    if (group.getSpecialization() != null) {
+                        valueParam = group.getSpecialization().getSignatureParameter(typeGuard.getSignatureIndex());
+                    } else {
+                        valueParam = node.getGenericSpecialization().getSignatureParameter(typeGuard.getSignatureIndex());
+                    }
+                }
+
+                NodeExecutionData execution = valueParam.getSpecification().getExecution();
+                CodeTree implicitGuard = createTypeGuard(guardsBuilder, execution, valueParam, typeGuard.getType(), typedCasts);
+                if (implicitGuard != null) {
+                    guardsBuilder.string(guardsAnd);
+                    guardsBuilder.tree(implicitGuard);
+                    guardsAnd = " && ";
+                }
+
+                CodeTree implicitGetType = null;
+                if (castForGuardsOnly) {
+                    implicitGetType = createGetImplicitType(builder, execution, valueParam, typeGuard.getType());
+                }
+
+                boolean performCast = true;
+                if (castForGuardsOnly) {
+                    // if cast for guards we just cast if the type guard is used inside a guard.
+                    performCast = group.isTypeGuardUsedInAnyGuardBelow(context, source, typeGuard);
+                }
+
+                if (performCast) {
+                    CodeTree cast = createCast(castBuilder, execution, valueParam, typeGuard.getType(), typedCasts);
+                    if (cast != null) {
+                        castBuilder.tree(cast);
+                    }
+                }
+                if (implicitGetType != null) {
+                    castBuilder.tree(implicitGetType);
+                }
+            }
+            List<GuardExpression> elseGuards = group.findElseConnectableGuards();
+
+            for (GuardExpression guard : group.getGuards()) {
+                if (elseGuards.contains(guard)) {
+                    continue;
+                }
+
+                if (needsTypeGuard(source, group, guard)) {
+                    guardsCastBuilder.tree(createMethodGuard(builder, guardsCastAnd, source, guard));
+                    guardsCastAnd = " && ";
+                } else {
+                    guardsBuilder.tree(createMethodGuard(builder, guardsAnd, source, guard));
+                    guardsAnd = " && ";
+                }
+            }
+
+            int ifCount = startGuardIf(builder, guardsBuilder, 0, elseGuards);
+            builder.tree(castBuilder.getRoot());
+            ifCount = startGuardIf(builder, guardsCastBuilder, ifCount, elseGuards);
+            return ifCount;
+        }
+
+        private int startGuardIf(CodeTreeBuilder builder, CodeTreeBuilder conditionBuilder, int ifCount, List<GuardExpression> elseGuard) {
+            int newIfCount = ifCount;
+
+            if (!conditionBuilder.isEmpty()) {
+                if (ifCount == 0 && !elseGuard.isEmpty()) {
+                    builder.startElseIf();
+                } else {
+                    builder.startIf();
+                }
+                builder.tree(conditionBuilder.getRoot());
+                builder.end().startBlock();
+                newIfCount++;
+            } else if (ifCount == 0 && !elseGuard.isEmpty()) {
+                builder.startElseBlock();
+                newIfCount++;
+            }
+            return newIfCount;
+        }
+
+        private boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardExpression guard) {
+            int signatureIndex = 0;
+            for (Parameter parameter : guard.getResolvedGuard().getParameters()) {
+                if (!parameter.getSpecification().isSignature()) {
+                    continue;
+                }
+
+                TypeGuard typeGuard = group.findTypeGuard(signatureIndex);
+                if (typeGuard != null) {
+                    TypeData requiredType = typeGuard.getType();
+
+                    Parameter sourceParameter = source.findParameter(parameter.getLocalName());
+                    if (sourceParameter == null) {
+                        sourceParameter = source.getNode().getGenericSpecialization().findParameter(parameter.getLocalName());
+                    }
+
+                    if (ElementUtils.needsCastTo(sourceParameter.getType(), requiredType.getPrimitiveType())) {
+                        return true;
+                    }
+                }
+
+                signatureIndex++;
+            }
+            return false;
+        }
+
+        private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeExecutionData execution, Parameter source, TypeData targetType, boolean typedCasts) {
+            NodeData node = execution.getChild().getNodeData();
+
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+
+            TypeData sourceType = source.getTypeSystemType();
+
+            if (!sourceType.needsCastTo(targetType)) {
+                return null;
+            }
+
+            builder.startGroup();
+
+            if (execution.isShortCircuit()) {
+                Parameter shortCircuit = source.getPreviousParameter();
+                assert shortCircuit != null;
+                builder.string("(");
+                builder.string("!").string(valueName(shortCircuit));
+                builder.string(" || ");
+            }
+
+            String castMethodName;
+            String castTypeName = null;
+            List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
+            if (types.size() > 1) {
+                castMethodName = TypeSystemCodeGenerator.isImplicitTypeMethodName(targetType);
+                if (typedCasts) {
+                    castTypeName = implicitTypeName(source);
+                }
+            } else {
+                castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType);
+            }
+
+            startCallTypeSystemMethod(builder, node.getTypeSystem(), castMethodName);
+            builder.string(valueName(source));
+            if (castTypeName != null) {
+                builder.string(castTypeName);
+            }
+            builder.end().end(); // call
+
+            if (execution.isShortCircuit()) {
+                builder.string(")");
+            }
+
+            builder.end(); // group
+
+            return builder.getRoot();
+        }
+
+        // TODO merge redundancies with #createTypeGuard
+        private CodeTree createCast(CodeTreeBuilder parent, NodeExecutionData execution, Parameter source, TypeData targetType, boolean typedCasts) {
+            NodeData node = execution.getChild().getNodeData();
+            TypeData sourceType = source.getTypeSystemType();
+
+            if (!sourceType.needsCastTo(targetType)) {
+                return null;
+            }
+
+            CodeTree condition = null;
+            if (execution.isShortCircuit()) {
+                Parameter shortCircuit = source.getPreviousParameter();
+                assert shortCircuit != null;
+                condition = CodeTreeBuilder.singleString(valueName(shortCircuit));
+            }
+
+            String castMethodName;
+            String castTypeName = null;
+            List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
+            if (types.size() > 1) {
+                castMethodName = TypeSystemCodeGenerator.asImplicitTypeMethodName(targetType);
+                if (typedCasts) {
+                    castTypeName = implicitTypeName(source);
+                }
+            } else {
+                castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
+            }
+
+            List<CodeTree> args = new ArrayList<>();
+            args.add(CodeTreeBuilder.singleString(valueName(source)));
+            if (castTypeName != null) {
+                args.add(CodeTreeBuilder.singleString(castTypeName));
+            }
+
+            CodeTree cast = createCallTypeSystemMethod(parent, node, castMethodName, args.toArray(new CodeTree[0]));
+
+            CodeTreeBuilder builder = parent.create();
+            builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, cast));
+
+            return builder.getRoot();
+        }
+
+        private CodeTree createGetImplicitType(CodeTreeBuilder parent, NodeExecutionData execution, Parameter source, TypeData targetType) {
+            CodeTree condition = null;
+            if (execution.isShortCircuit()) {
+                Parameter shortCircuit = source.getPreviousParameter();
+                assert shortCircuit != null;
+                condition = CodeTreeBuilder.singleString(valueName(shortCircuit));
+            }
+
+            CodeTreeBuilder builder = parent.create();
+            List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
+            if (types.size() > 1) {
+                CodeTree castType = createCallTypeSystemMethod(parent, execution.getChild().getNodeData(), TypeSystemCodeGenerator.getImplicitClass(targetType),
+                                CodeTreeBuilder.singleString(valueName(source)));
+                builder.tree(createLazyAssignment(builder, implicitTypeName(source), getContext().getType(Class.class), condition, castType));
+            }
+            return builder.getRoot();
+        }
+
+        private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardExpression guard) {
+            CodeTreeBuilder builder = parent.create();
+            builder.string(prefix);
+            if (guard.isNegated()) {
+                builder.string("!");
+            }
+            builder.tree(createTemplateMethodCall(builder, null, source, guard.getResolvedGuard(), null));
+            return builder.getRoot();
+        }
+
+        protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+
+            if (current.getMethod() == null) {
+                emitEncounteredSynthetic(builder, current);
+            } else {
+                builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end();
+            }
+
+            return encloseThrowsWithFallThrough(current, builder.getRoot());
+        }
+
+        private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree) {
+            if (current.getExceptions().isEmpty()) {
+                return tree;
+            }
+            CodeTreeBuilder builder = new CodeTreeBuilder(null);
+
+            builder.startTryBlock();
+            builder.tree(tree);
+            for (SpecializationThrowsData exception : current.getExceptions()) {
+                builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx");
+                builder.tree(createDeoptimize(builder));
+                builder.tree(createCallRewriteMonomorphic(builder, false, current.getNode().getGenericSpecialization().getReturnType().getTypeSystemType(), current, null,
+                                "Thrown " + ElementUtils.getSimpleName(exception.getJavaClass())));
+            }
+            builder.end();
+
+            return builder.getRoot();
+        }
+
+        protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) {
+            TypeData type = executable.getType();
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            NodeData node = specialization.getNode();
+
+            TypeData primaryType = castExecutable.getType();
+
+            boolean needsTry = castExecutable.hasUnexpectedValue(getContext());
+            boolean returnVoid = type.isVoid();
+
+            List<Parameter> executeParameters = new ArrayList<>();
+            for (Parameter sourceParameter : executable.getSignatureParameters()) {
+                Parameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName());
+                if (targetParameter != null) {
+                    executeParameters.add(targetParameter);
+                }
+            }
+
+            // execute names are enforced no cast
+            String[] executeParameterNames = new String[executeParameters.size()];
+            for (int i = 0; i < executeParameterNames.length; i++) {
+                executeParameterNames[i] = valueName(executeParameters.get(i));
+            }
+
+            builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null));
+            boolean hasUnexpected = executable.hasUnexpectedValue(getContext());
+
+            CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames);
+            if (needsTry) {
+                if (!returnVoid) {
+                    builder.declaration(primaryType.getPrimitiveType(), "value");
+                }
+                builder.startTryBlock();
+
+                if (returnVoid) {
+                    builder.statement(primaryExecuteCall);
+                } else {
+                    builder.startStatement();
+                    builder.string("value = ");
+                    builder.tree(primaryExecuteCall);
+                    builder.end();
+                }
+
+                builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
+                if (returnVoid) {
+                    builder.string("// ignore").newLine();
+                } else {
+                    builder.startReturn();
+                    builder.tree(createExpectExecutableType(node, specialization.getNode().getTypeSystem().getGenericTypeData(), hasUnexpected, executable.getType(),
+                                    CodeTreeBuilder.singleString("ex.getResult()")));
+                    builder.end();
+                }
+                builder.end();
+
+                if (!returnVoid) {
+                    builder.startReturn();
+                    builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), hasUnexpected, executable.getType(), CodeTreeBuilder.singleString("value")));
+                    builder.end();
+                }
+            } else {
+                if (returnVoid) {
+                    builder.statement(primaryExecuteCall);
+                } else {
+                    builder.startReturn();
+                    builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), hasUnexpected, executable.getType(), primaryExecuteCall));
+                    builder.end();
+                }
+            }
+
+            return builder.getRoot();
+        }
+
+        protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, boolean hasUnexpected, TypeData exepctedType, CodeTree value) {
+            return createCastType(node.getTypeSystem(), sourceType, exepctedType, hasUnexpected, value);
+        }
+
+        protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<Parameter> targetParameters,
+                        Parameter unexpectedParameter) {
+            CodeTreeBuilder builder = parent.create();
+            for (Parameter targetParameter : targetParameters) {
+                if (!targetParameter.getSpecification().isSignature()) {
+                    continue;
+                }
+                NodeExecutionData execution = targetParameter.getSpecification().getExecution();
+                CodeTree executionExpressions = createExecuteChild(builder, execution, sourceExecutable, targetParameter, unexpectedParameter);
+                CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, specialization, sourceExecutable, targetParameter, execution.isShortCircuit(), unexpectedParameter);
+                CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, specialization, targetParameter, unexpectedParameter);
+
+                if (shortCircuitTree == executionExpressions) {
+                    if (containsNewLine(executionExpressions)) {
+                        builder.declaration(targetParameter.getType(), valueName(targetParameter));
+                        builder.tree(shortCircuitTree);
+                    } else {
+                        builder.startStatement().type(targetParameter.getType()).string(" ").tree(shortCircuitTree).end();
+                    }
+                } else {
+                    builder.tree(shortCircuitTree);
+                }
+
+            }
+            return builder.getRoot();
+        }
+
+        private ExecutableTypeData resolveExecutableType(NodeExecutionData execution, TypeData type) {
+            ExecutableTypeData targetExecutable = execution.getChild().findExecutableType(getContext(), type);
+            if (targetExecutable == null) {
+                targetExecutable = execution.getChild().findAnyGenericExecutableType(getContext());
+            }
+            return targetExecutable;
+        }
+
+        private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, Parameter targetParameter, Parameter unexpectedParameter) {
+            SpecializationData specialization = getModel();
+            TreeSet<TypeData> possiblePolymorphicTypes = lookupPolymorphicTargetTypes(targetParameter);
+            if (specialization.isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null && possiblePolymorphicTypes.size() > 1) {
+
+                CodeTreeBuilder builder = parent.create();
+
+                boolean elseIf = false;
+                for (TypeData possiblePolymoprhicType : possiblePolymorphicTypes) {
+                    if (possiblePolymoprhicType.isGeneric()) {
+                        continue;
+                    }
+                    elseIf = builder.startIf(elseIf);
+
+                    Parameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName());
+                    TypeData sourceType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null;
+                    builder.string(polymorphicTypeName(targetParameter.getSpecification().getExecution())).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType());
+                    builder.end().startBlock();
+                    builder.startStatement();
+                    builder.tree(createExecuteChildExpression(parent, execution, sourceType, new Parameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null));
+                    builder.end();
+                    builder.end();
+                }
+
+                builder.startElseBlock();
+                builder.startStatement().tree(createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter)).end();
+                builder.end();
+
+                return builder.getRoot();
+            } else {
+                return createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter);
+            }
+        }
+
+        protected final List<Parameter> getImplicitTypeParameters(SpecializationData model) {
+            List<Parameter> parameter = new ArrayList<>();
+            for (Parameter param : model.getSignatureParameters()) {
+                NodeChildData child = param.getSpecification().getExecution().getChild();
+                List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
+                if (types.size() > 1) {
+                    parameter.add(param);
+                }
+            }
+            return parameter;
+        }
+
+        protected final TreeSet<TypeData> lookupPolymorphicTargetTypes(Parameter param) {
+            SpecializationData specialization = getModel();
+            TreeSet<TypeData> possiblePolymorphicTypes = new TreeSet<>();
+            for (SpecializationData otherSpecialization : specialization.getNode().getSpecializations()) {
+                if (!otherSpecialization.isSpecialized()) {
+                    continue;
+                }
+                Parameter otherParameter = otherSpecialization.findParameter(param.getLocalName());
+                if (otherParameter != null) {
+                    possiblePolymorphicTypes.add(otherParameter.getTypeSystemType());
+                }
+            }
+            return possiblePolymorphicTypes;
+        }
+
+        private CodeTree createExecuteChildImplicit(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, Parameter param, Parameter unexpectedParameter) {
+            CodeTreeBuilder builder = parent.create();
+            Parameter sourceParameter = sourceExecutable.findParameter(param.getLocalName());
+            String childExecuteName = createExecuteChildMethodName(param, sourceParameter != null);
+            if (childExecuteName != null) {
+                builder.string(valueName(param));
+                builder.string(" = ");
+                builder.startCall(childExecuteName);
+
+                for (Parameter parameters : sourceExecutable.getParameters()) {
+                    if (parameters.getSpecification().isSignature()) {
+                        continue;
+                    }
+                    builder.string(parameters.getLocalName());
+                }
+
+                if (sourceParameter != null) {
+                    builder.string(valueNameEvaluated(sourceParameter));
+                }
+
+                builder.string(implicitTypeName(param));
+
+                builder.end();
+            } else {
+                List<TypeData> sourceTypes = execution.getChild().getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
+                TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null;
+                if (sourceTypes.size() > 1) {
+                    builder.tree(createExecuteChildImplicitExpressions(parent, param, expectType));
+                } else {
+                    builder.tree(createExecuteChildExpression(parent, execution, expectType, param, unexpectedParameter, null));
+                }
+            }
+            return builder.getRoot();
+        }
+
+        private String createExecuteChildMethodName(Parameter param, boolean expect) {
+            NodeExecutionData execution = param.getSpecification().getExecution();
+            NodeChildData child = execution.getChild();
+            if (child.getExecuteWith().size() > 0) {
+                return null;
+            }
+            List<TypeData> sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
+            if (sourceTypes.size() <= 1) {
+                return null;
+            }
+            String prefix = expect ? "expect" : "execute";
+            String suffix = execution.getIndex() > -1 ? String.valueOf(execution.getIndex()) : "";
+            return prefix + ElementUtils.firstLetterUpperCase(child.getName()) + ElementUtils.firstLetterUpperCase(ElementUtils.getSimpleName(param.getType())) + suffix;
+        }
+
+        private List<CodeExecutableElement> createExecuteChilds(Parameter param, Set<TypeData> expectTypes) {
+            CodeExecutableElement executeMethod = createExecuteChild(param, null);
+            if (executeMethod == null) {
+                return Collections.emptyList();
+            }
+            List<CodeExecutableElement> childs = new ArrayList<>();
+            childs.add(executeMethod);
+
+            for (TypeData expectType : expectTypes) {
+                CodeExecutableElement method = createExecuteChild(param, expectType);
+                if (method != null) {
+                    childs.add(method);
+                }
+            }
+            return childs;
+        }
+
+        private CodeExecutableElement createExecuteChild(Parameter param, TypeData expectType) {
+            String childExecuteName = createExecuteChildMethodName(param, expectType != null);
+            if (childExecuteName == null) {
+                return null;
+            }
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, expectType != null ? STATIC : FINAL), param.getType(), childExecuteName);
+            method.getThrownTypes().add(getContext().getTruffleTypes().getUnexpectedValueException());
+            method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
+            if (expectType != null) {
+                method.addParameter(new CodeVariableElement(expectType.getPrimitiveType(), valueNameEvaluated(param)));
+            }
+            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param)));
+
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.declaration(param.getType(), valueName(param));
+            builder.tree(createExecuteChildImplicitExpressions(builder, param, expectType));
+            builder.startReturn().string(valueName(param)).end();
+
+            return method;
+        }
+
+        private CodeTree createExecuteChildImplicitExpressions(CodeTreeBuilder parent, Parameter targetParameter, TypeData expectType) {
+            CodeTreeBuilder builder = parent.create();
+            NodeData node = getModel().getNode();
+            NodeExecutionData execution = targetParameter.getSpecification().getExecution();
+            List<TypeData> sourceTypes = node.getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType());
+            boolean elseIf = false;
+            int index = 0;
+            for (TypeData sourceType : sourceTypes) {
+                if (index < sourceTypes.size() - 1) {
+                    elseIf = builder.startIf(elseIf);
+                    builder.string(implicitTypeName(targetParameter)).string(" == ").typeLiteral(sourceType.getPrimitiveType());
+                    builder.end();
+                    builder.startBlock();
+                } else {
+                    builder.startElseBlock();
+                }
+
+                ExecutableTypeData implictExecutableTypeData = execution.getChild().findExecutableType(getContext(), sourceType);
+                if (implictExecutableTypeData == null) {
+                    /*
+                     * For children with executeWith.size() > 0 an executable type may not exist so
+                     * use the generic executable type which is guaranteed to exist. An expect call
+                     * is inserted automatically by #createExecuteExpression.
+                     */
+                    implictExecutableTypeData = execution.getChild().getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), execution.getChild().getExecuteWith().size());
+                }
+
+                ImplicitCastData cast = execution.getChild().getNodeData().getTypeSystem().lookupCast(sourceType, targetParameter.getTypeSystemType());
+                CodeTree execute = createExecuteChildExpression(builder, execution, expectType, targetParameter, null, cast);
+                builder.statement(execute);
+                builder.end();
+                index++;
+            }
+            return builder.getRoot();
+        }
+
+        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData execution, TypeData sourceParameterType, Parameter targetParameter, Parameter unexpectedParameter,
+                        ImplicitCastData cast) {
+            // assignments: targetType <- castTargetType <- castSourceType <- sourceType
+            TypeData sourceType = sourceParameterType;
+            TypeData targetType = targetParameter.getTypeSystemType();
+            TypeData castSourceType = targetType;
+            TypeData castTargetType = targetType;
+
+            if (cast != null) {
+                castSourceType = cast.getSourceType();
+                castTargetType = cast.getTargetType();
+            }
+
+            CodeTree expression;
+            if (sourceType == null) {
+                ExecutableTypeData targetExecutable = resolveExecutableType(execution, castSourceType);
+                expression = createExecuteChildExpression(parent, execution, targetExecutable, unexpectedParameter);
+                sourceType = targetExecutable.getType();
+            } else {
+                expression = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter));
+            }
+
+            // target = expectTargetType(implicitCast(expectCastSourceType(source)))
+            TypeSystemData typeSystem = execution.getChild().getNodeData().getTypeSystem();
+            expression = createExpectType(typeSystem, sourceType, castSourceType, expression);
+            expression = createImplicitCast(parent, typeSystem, cast, expression);
+            expression = createExpectType(typeSystem, castTargetType, targetType, expression);
+
+            CodeTreeBuilder builder = parent.create();
+            builder.string(valueName(targetParameter));
+            builder.string(" = ");
+            builder.tree(expression);
+            return builder.getRoot();
+        }
+
+        private CodeTree createImplicitCast(CodeTreeBuilder parent, TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) {
+            if (cast == null) {
+                return expression;
+            }
+            CodeTreeBuilder builder = parent.create();
+            startCallTypeSystemMethod(builder, typeSystem, cast.getMethodName());
+            builder.tree(expression);
+            builder.end().end();
+            return builder.getRoot();
+        }
+
+        private boolean containsNewLine(CodeTree tree) {
+            if (tree.getCodeKind() == CodeTreeKind.NEW_LINE) {
+                return true;
+            }
+
+            for (CodeTree codeTree : tree.getEnclosedElements()) {
+                if (containsNewLine(codeTree)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        private boolean hasUnexpected(Parameter sourceParameter, Parameter targetParameter, Parameter unexpectedParameter) {
+            NodeExecutionData execution = targetParameter.getSpecification().getExecution();
+
+            if (getModel().isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) {
+                // check for other polymorphic types
+                TreeSet<TypeData> polymorphicTargetTypes = lookupPolymorphicTargetTypes(targetParameter);
+                if (polymorphicTargetTypes.size() > 1) {
+                    for (TypeData polymorphicTargetType : polymorphicTargetTypes) {
+                        if (hasUnexpectedType(execution, sourceParameter, polymorphicTargetType)) {
+                            return true;
+                        }
+                    }
+                }
+            }
+
+            if (hasUnexpectedType(execution, sourceParameter, targetParameter.getTypeSystemType())) {
+                return true;
+            }
+            return false;
+        }
+
+        private boolean hasUnexpectedType(NodeExecutionData execution, Parameter sourceParameter, TypeData targetType) {
+            List<TypeData> implicitSourceTypes = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
+
+            for (TypeData implicitSourceType : implicitSourceTypes) {
+                TypeData sourceType;
+                ExecutableTypeData targetExecutable = resolveExecutableType(execution, implicitSourceType);
+                if (sourceParameter != null) {
+                    sourceType = sourceParameter.getTypeSystemType();
+                } else {
+                    if (targetExecutable.hasUnexpectedValue(getContext())) {
+                        return true;
+                    }
+                    sourceType = targetExecutable.getType();
+                }
+
+                ImplicitCastData cast = getModel().getNode().getTypeSystem().lookupCast(implicitSourceType, targetType);
+                if (cast != null) {
+                    if (cast.getSourceType().needsCastTo(targetType)) {
+                        return true;
+                    }
+                }
+
+                if (sourceType.needsCastTo(targetType)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ExecutableTypeData currentExecutable, Parameter param,
+                        boolean shortCircuit, Parameter unexpectedParameter) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            Parameter sourceParameter = currentExecutable.findParameter(param.getLocalName());
+            boolean unexpected = hasUnexpected(sourceParameter, param, unexpectedParameter);
+            if (!unexpected) {
+                return body;
+            }
+
+            if (!shortCircuit) {
+                builder.declaration(param.getType(), valueName(param));
+            }
+            builder.startTryBlock();
+
+            if (containsNewLine(body)) {
+                builder.tree(body);
+            } else {
+                builder.statement(body);
+            }
+
+            builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
+            SpecializationData generic = specialization.getNode().getGenericSpecialization();
+            Parameter genericParameter = generic.findParameter(param.getLocalName());
+
+            List<Parameter> genericParameters = generic.getParametersAfter(genericParameter);
+            builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter));
+            if (specialization.isPolymorphic()) {
+                builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param));
+            } else {
+                builder.tree(createCallRewriteMonomorphic(builder, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), specialization, param,
+                                "Expected " + param.getLocalName() + " instanceof " + ElementUtils.getSimpleName(param.getType())));
+            }
+            builder.end(); // catch block
+
+            return builder.getRoot();
+        }
+
+        private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, Parameter param) {
+            NodeData node = specialization.getNode();
+            SpecializationData polymorphic = node.getPolymorphicSpecialization();
+
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            builder.startStatement().string(polymorphicTypeName(param.getSpecification().getExecution())).string(" = ").typeLiteral(getContext().getType(Object.class)).end();
+
+            builder.startReturn();
+
+            CodeTreeBuilder execute = new CodeTreeBuilder(builder);
+            execute.startCall("next0", EXECUTE_CHAINED);
+            addInternalValueParameterNames(execute, specialization, polymorphic, param.getLocalName(), true, null);
+            execute.end();
+
+            TypeData sourceType = polymorphic.getReturnType().getTypeSystemType();
+
+            builder.tree(createExpectExecutableType(node, sourceType, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), execute.getRoot()));
+
+            builder.end();
+            return builder.getRoot();
+        }
+
+        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData targetExecution, ExecutableTypeData targetExecutable, Parameter unexpectedParameter) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            if (targetExecution != null) {
+                builder.tree(createAccessChild(targetExecution, null));
+                builder.string(".");
+            }
+
+            builder.startCall(targetExecutable.getMethodName());
+
+            // TODO this should be merged with #createTemplateMethodCall
+            int index = 0;
+            for (Parameter parameter : targetExecutable.getParameters()) {
+
+                if (!parameter.getSpecification().isSignature()) {
+                    builder.string(parameter.getLocalName());
+                } else {
+
+                    if (index < targetExecution.getChild().getExecuteWith().size()) {
+                        NodeChildData child = targetExecution.getChild().getExecuteWith().get(index);
+
+                        ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName());
+                        List<Parameter> specializationParams = getModel().findParameters(spec);
+
+                        if (specializationParams.isEmpty()) {
+                            builder.defaultValue(parameter.getType());
+                            continue;
+                        }
+
+                        Parameter specializationParam = specializationParams.get(0);
+
+                        TypeData targetType = parameter.getTypeSystemType();
+                        TypeData sourceType = specializationParam.getTypeSystemType();
+                        String localName = specializationParam.getLocalName();
+
+                        if (unexpectedParameter != null && unexpectedParameter.getLocalName().equals(specializationParam.getLocalName())) {
+                            localName = "ex.getResult()";
+                            sourceType = getModel().getNode().getTypeSystem().getGenericTypeData();
+                        }
+
+                        CodeTree value = CodeTreeBuilder.singleString(localName);
+
+                        if (sourceType.needsCastTo(targetType)) {
+                            value = createCallTypeSystemMethod(builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value);
+                        }
+                        builder.tree(value);
+                    } else {
+                        builder.defaultValue(parameter.getType());
+                    }
+                    index++;
+                }
+            }
+
+            builder.end();
+
+            return builder.getRoot();
+        }
+
+        private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, Parameter parameter, Parameter exceptionParam) {
+            NodeExecutionData execution = parameter.getSpecification().getExecution();
+            if (execution == null || !execution.isShortCircuit()) {
+                return body;
+            }
+
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            Parameter shortCircuitParam = specialization.getPreviousParam(parameter);
+            builder.tree(createShortCircuitValue(builder, specialization, execution, shortCircuitParam, exceptionParam));
+            builder.declaration(parameter.getType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getType()));
+            builder.startIf().string(shortCircuitParam.getLocalName()).end();
+            builder.startBlock();
+
+            if (containsNewLine(body)) {
+                builder.tree(body);
+            } else {
+                builder.statement(body);
+            }
+            builder.end();
+
+            return builder.getRoot();
+        }
+
+        private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeExecutionData execution, Parameter shortCircuitParam, Parameter exceptionParam) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            int shortCircuitIndex = 0;
+            for (NodeExecutionData otherExectuion : specialization.getNode().getChildExecutions()) {
+                if (otherExectuion.isShortCircuit()) {
+                    if (otherExectuion == execution) {
+                        break;
+                    }
+                    shortCircuitIndex++;
+                }
+            }
+
+            builder.startStatement().type(shortCircuitParam.getType()).string(" ").string(valueName(shortCircuitParam)).string(" = ");
+            ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex);
+            builder.tree(createTemplateMethodCall(builder, null, specialization, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null));
+            builder.end(); // statement
+
+            return builder.getRoot();
+        }
+
+        protected CodeTree createCallRewriteMonomorphic(CodeTreeBuilder parent, boolean hasUnexpected, TypeData returnType, SpecializationData current, Parameter exceptionParam, String reason) {
+            NodeData node = current.getNode();
+            SpecializationData generic = node.getGenericSpecialization();
+            CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
+            specializeCall.startCall(REWRITE);
+            addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, null);
+            specializeCall.doubleQuote(reason);
+            specializeCall.end().end();
+
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+
+            builder.startReturn();
+            builder.tree(createExpectExecutableType(node, generic.getReturnType().getTypeSystemType(), hasUnexpected, returnType, specializeCall.getRoot()));
+            builder.end();
+
+            return builder.getRoot();
+        }
+
+    }
+
+    private class PolymorphicNodeFactory extends SpecializedNodeFactory {
+
+        public PolymorphicNodeFactory(CodeTypeElement nodeGen) {
+            super(nodeGen);
+        }
+
+        @Override
+        public CodeTypeElement create(SpecializationData polymorph) {
+            NodeData node = polymorph.getNode();
+            TypeMirror baseType = node.getNodeType();
+            if (nodeGen != null) {
+                baseType = nodeGen.asType();
+            }
+            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false);
+
+            clazz.getAnnotationMirrors().add(createNodeInfo(node, NodeCost.POLYMORPHIC));
+
+            for (Parameter polymorphParameter : polymorph.getSignatureParameters()) {
+                if (!polymorphParameter.getTypeSystemType().isGeneric()) {
+                    continue;
+                }
+                Set<TypeData> types = new HashSet<>();
+                for (SpecializationData specialization : node.getSpecializations()) {
+                    if (!specialization.isSpecialized()) {
+                        continue;
+                    }
+                    Parameter parameter = specialization.findParameter(polymorphParameter.getLocalName());
+                    assert parameter != null;
+                    types.add(parameter.getTypeSystemType());
+                }
+
+            }
+
+            for (NodeExecutionData execution : getModel().getNode().getChildExecutions()) {
+                String fieldName = polymorphicTypeName(execution);
+                CodeVariableElement var = new CodeVariableElement(modifiers(PRIVATE), getContext().getType(Class.class), fieldName);
+                var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getCompilationFinal()));
+                clazz.add(var);
+            }
+
+            return clazz;
+        }
+
+        @Override
+        protected void createChildren(SpecializationData specialization) {
+            CodeTypeElement clazz = getElement();
+
+            createConstructors(clazz);
+            createExecuteMethods(specialization);
+
+            clazz.add(createUpdateTypes0());
+            createCachedExecuteMethods(specialization);
+        }
+
+    }
+
+    private class SpecializedNodeFactory extends NodeBaseFactory {
+
+        protected final CodeTypeElement nodeGen;
+
+        public SpecializedNodeFactory(CodeTypeElement nodeGen) {
+            this.nodeGen = nodeGen;
+        }
+
+        @Override
+        public CodeTypeElement create(SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            TypeMirror baseType = node.getNodeType();
+            if (nodeGen != null) {
+                baseType = nodeGen.asType();
+            }
+            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false);
+
+            if (specialization.isSpecialized() || specialization.isUninitialized()) {
+                clazz.add(createGetMetadata0(false));
+                clazz.add(createMetadataLiteral());
+            }
+
+            NodeCost cost;
+            if (specialization.isGeneric()) {
+                cost = NodeCost.MEGAMORPHIC;
+            } else if (specialization.isUninitialized()) {
+                cost = NodeCost.UNINITIALIZED;
+            } else if (specialization.isPolymorphic()) {
+                cost = NodeCost.POLYMORPHIC;
+            } else if (specialization.isSpecialized()) {
+                cost = NodeCost.MONOMORPHIC;
+            } else {
+                throw new AssertionError();
+            }
+            clazz.getAnnotationMirrors().add(createNodeInfo(node, cost));
+
+            if (specialization.isUninitialized() && node.getGenericSpecialization().isReachable()) {
+                clazz.add(createUninitializedGetCostOverride());
+            }
+
+            return clazz;
+        }
+
+        private Element createUninitializedGetCostOverride() {
+            TypeMirror returnType = context.getTruffleTypes().getNodeCost();
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getCost");
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startIf().string(CONTAINS_FALLBACK).end().startBlock();
+            builder.startReturn().staticReference(returnType, "MONOMORPHIC").end();
+            builder.end();
+            builder.startReturn().string("super.getCost()").end();
+            return method;
+        }
+
+        private CodeVariableElement createMetadataLiteral() {
+            CodeVariableElement includes = new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), context.getTruffleTypes().getDslMetadata(), METADATA_FIELD_NAME);
+
+            CodeTreeBuilder builder = includes.createInitBuilder();
+
+            SpecializationData specialization = getModel();
+            NodeData node = specialization.getNode();
+
+            Set<SpecializationData> contains = specialization.getContains();
+            if (specialization.isUninitialized()) {
+                contains = new HashSet<>();
+
+                SpecializationData polymorphic = node.getPolymorphicSpecialization();
+                if (polymorphic != null) {
+                    contains.addAll(polymorphic.getContains());
+                }
+                SpecializationData generic = node.getGenericSpecialization();
+                if (generic != null) {
+                    contains.addAll(generic.getContains());
+                }
+            }
+
+            builder.startNew(context.getTruffleTypes().getDslMetadata());
+            builder.startGroup().string(nodeSpecializationClassName(getModel()), ".class").end();
+            builder.tree(createSpecializationListLiteral(builder, contains));
+            builder.tree(createSpecializationListLiteral(builder, getModel().getExcludedBy()));
+            builder.tree(createSpecializationTypeLiteral(builder, SpecializationData.getSignatureTypes(getModel())));
+            builder.string("0").string("0");
+            builder.end();
+            return includes;
+        }
+
+        private CodeTree createSpecializationTypeLiteral(CodeTreeBuilder parent, List<TypeMirror> list) {
+            ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class));
+            CodeTreeBuilder builder = parent.create();
+
+            if (list.isEmpty()) {
+                builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
+            } else {
+                builder.startNewArray(classArray, null);
+                for (TypeMirror type : list) {
+                    builder.typeLiteral(type);
+                }
+                builder.end();
+            }
+
+            return builder.getRoot();
+        }
+
+        private CodeTree createSpecializationListLiteral(CodeTreeBuilder parent, Set<SpecializationData> list) {
+            ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class));
+            CodeTreeBuilder builder = parent.create();
+
+            if (list.isEmpty()) {
+                builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
+            } else {
+                builder.startNewArray(classArray, null);
+                for (SpecializationData specialization : list) {
+                    if (specialization.isGeneric() || specialization.isPolymorphic()) {
+                        specialization = getModel().getNode().getUninitializedSpecialization();
+                    }
+                    builder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end();
+                }
+                builder.end();
+            }
+
+            return builder.getRoot();
+        }
+
+        protected CodeAnnotationMirror createNodeInfo(NodeData node, NodeCost cost) {
+            String shortName = node.getShortName();
+            CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation());
+            if (shortName != null) {
+                nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName));
+            }
+
+            DeclaredType nodeinfoCost = getContext().getTruffleTypes().getNodeCost();
+            VariableElement varKind = ElementUtils.findVariableElement(nodeinfoCost, cost.name());
+
+            nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("cost"), new CodeAnnotationValue(varKind));
+            return nodeInfoMirror;
+        }
+
+        @Override
+        protected void createChildren(SpecializationData specialization) {
+            CodeTypeElement clazz = getElement();
+            createConstructors(clazz);
+
+            createExecuteMethods(specialization);
+            createCachedExecuteMethods(specialization);
+
+            if (specialization.isUninitialized()) {
+                if (specialization.getNode().isFallbackReachable()) {
+                    CodeVariableElement var = new CodeVariableElement(modifiers(Modifier.PRIVATE), context.getType(boolean.class), CONTAINS_FALLBACK);
+                    var.addAnnotationMirror(new CodeAnnotationMirror(context.getTruffleTypes().getCompilationFinal()));
+                    clazz.add(var);
+                }
+                clazz.add(createExecuteUninitialized());
+            }
+
+            if (!specialization.isUninitialized() && specialization.getNode().needsRewrites(context)) {
+                clazz.add(createCopyConstructorFactoryMethod(nodeGen.asType(), specialization));
+            } else {
+                for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
+                    if (constructor.getParameters().size() == 1 && ((CodeVariableElement) constructor.getParameters().get(0)).getType().equals(nodeGen.asType())) {
+                        // skip copy constructor - not used
+                        continue;
+                    }
+                    clazz.add(createConstructorFactoryMethod(specialization, constructor));
+                }
+            }
+        }
+
+        protected void createConstructors(CodeTypeElement clazz) {
+            TypeElement superTypeElement = ElementUtils.fromTypeMirror(clazz.getSuperclass());
+            SpecializationData specialization = getModel();
+            NodeData node = specialization.getNode();
+            for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) {
+                if (specialization.isUninitialized()) {
+                    // ignore copy constructors for uninitialized if not polymorphic
+                    if (isCopyConstructor(constructor) && !node.isPolymorphic(context)) {
+                        continue;
+                    }
+                } else if (node.getUninitializedSpecialization() != null) {
+                    // ignore others than copy constructors for specialized nodes
+                    if (!isCopyConstructor(constructor)) {
+                        continue;
+                    }
+                }
+
+                CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor);
+                if (superConstructor == null) {
+                    continue;
+                }
+                CodeTree body = superConstructor.getBodyTree();
+                CodeTreeBuilder builder = superConstructor.createBuilder();
+                builder.tree(body);
+
+                if (superConstructor != null) {
+                    for (Parameter param : getImplicitTypeParameters(getModel())) {
+                        clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param)));
+                        superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param)));
+
+                        builder.startStatement();
+                        builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param));
+                        builder.end();
+                    }
+
+                    clazz.add(superConstructor);
+                }
+            }
+        }
+
+        protected void createExecuteMethods(SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            CodeTypeElement clazz = getElement();
+
+            for (ExecutableTypeData execType : node.getExecutableTypes()) {
+                if (execType.isFinal()) {
+                    continue;
+                }
+                CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, true);
+                clazz.add(executeMethod);
+                CodeTreeBuilder builder = executeMethod.getBuilder();
+                CodeTree result = createExecuteBody(builder, specialization, execType);
+                if (result != null) {
+                    builder.tree(result);
+                } else {
+                    clazz.remove(executeMethod);
+                }
+            }
+        }
+
+        protected void createCachedExecuteMethods(SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            if (!node.isPolymorphic(context)) {
+                return;
+            }
+
+            CodeTypeElement clazz = getElement();
+
+            final SpecializationData polymorphic = node.getPolymorphicSpecialization();
+            ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_CHAINED);
+            CodeExecutableElement executeMethod = CodeExecutableElement.clone(getContext().getEnvironment(), executeCached);
+            executeMethod.getModifiers().remove(Modifier.ABSTRACT);
+            CodeTreeBuilder builder = executeMethod.createBuilder();
+
+            if (specialization.isPolymorphic()) {
+                builder.startReturn().startCall("this.next0", EXECUTE_CHAINED);
+                addInternalValueParameterNames(builder, polymorphic, polymorphic, null, true, null);
+                builder.end().end();
+            } else if (specialization.isUninitialized()) {
+                if (node.getGenericSpecialization().isReachable()) {
+                    builder.startIf().string("!containsFallback").end().startBlock();
+                    builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
+                    builder.end();
+                } else {
+                    builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
+                }
+                builder.startReturn().startCall("this", EXECUTE_UNINITIALIZED);
+                addInternalValueParameterNames(builder, polymorphic, polymorphic, null, true, null);
+                builder.end().end();
+            } else {
+                CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder);
+                elseBuilder.startReturn().startCall("this.next0", EXECUTE_CHAINED);
+                addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, null);
+                elseBuilder.end().end();
+
+                builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), new CodeBlock<SpecializationData>() {
+
+                    public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
+                        return createGenericInvoke(b, polymorphic, current);
+                    }
+                }, elseBuilder.getRoot(), false, true, true, false));
+            }
+            clazz.add(executeMethod);
+        }
+
+        private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+
+            List<ExecutableTypeData> primaryExecutes = findFunctionalExecutableType(specialization, execType.getEvaluatedCount());
+
+            if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) {
+                builder.tree(createFunctionalExecute(builder, specialization, execType));
+            } else if (needsCastingExecuteMethod(execType)) {
+                assert !primaryExecutes.isEmpty();
+                builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0)));
+            } else {
+                return null;
+            }
+
+            return builder.getRoot();
+        }
+
+        private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) {
+            CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod());
+
+            method.getAnnotationMirrors().clear();
+            for (VariableElement variable : method.getParameters()) {
+                variable.getAnnotationMirrors().clear();
+            }
+
+            CodeTreeBuilder builder = method.createBuilder();
+            int i = 0;
+            int signatureIndex = -1;
+            for (VariableElement param : method.getParameters()) {
+                CodeVariableElement var = CodeVariableElement.clone(param);
+                Parameter actualParameter = i < execType.getParameters().size() ? execType.getParameters().get(i) : null;
+                String name;
+                if (actualParameter != null) {
+                    if (actualParameter.getSpecification().isSignature()) {
+                        signatureIndex++;
+                    }
+
+                    if (evaluated && actualParameter.getSpecification().isSignature()) {
+                        name = valueNameEvaluated(actualParameter);
+                    } else {
+                        name = valueName(actualParameter);
+                    }
+
+                    int varArgCount = getModel().getSignatureSize() - signatureIndex;
+                    if (evaluated && actualParameter.isTypeVarArgs()) {
+                        Parameter baseVarArgs = actualParameter;
+                        name = valueName(baseVarArgs) + "Args";
+
+                        builder.startAssert().string(name).string(" != null").end();
+                        builder.startAssert().string(name).string(".length == ").string(String.valueOf(varArgCount)).end();
+                        if (varArgCount > 0) {
+                            List<Parameter> varArgsParameter = execType.getParameters().subList(i, execType.getParameters().size());
+                            for (Parameter varArg : varArgsParameter) {
+                                if (varArgCount <= 0) {
+                                    break;
+                                }
+                                TypeMirror type = baseVarArgs.getType();
+                                if (type.getKind() == TypeKind.ARRAY) {
+                                    type = ((ArrayType) type).getComponentType();
+                                }
+                                builder.declaration(type, valueNameEvaluated(varArg), name + "[" + varArg.getTypeVarArgsIndex() + "]");
+                                varArgCount--;
+                            }
+                        }
+                    }
+                } else {
+                    name = "arg" + i;
+                }
+                var.setName(name);
+                method.getParameters().set(i, var);
+                i++;
+            }
+
+            method.getAnnotationMirrors().clear();
+            method.getModifiers().remove(Modifier.ABSTRACT);
+            return method;
+        }
+
+        private boolean needsCastingExecuteMethod(ExecutableTypeData execType) {
+            if (execType.isAbstract()) {
+                return true;
+            }
+            if (execType.getType().isGeneric()) {
+                return true;
+            }
+            return false;
+        }
+
+        private List<ExecutableTypeData> findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) {
+            TypeData primaryType = specialization.getReturnType().getTypeSystemType();
+            List<ExecutableTypeData> otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount);
+
+            List<ExecutableTypeData> filteredTypes = new ArrayList<>();
+            for (ExecutableTypeData compareType : otherTypes) {
+                if (!ElementUtils.typeEquals(compareType.getType().getPrimitiveType(), primaryType.getPrimitiveType())) {
+                    continue;
+                }
+                filteredTypes.add(compareType);
+            }
+
+            // no direct matches found use generic where the type is Object
+            if (filteredTypes.isEmpty()) {
+                for (ExecutableTypeData compareType : otherTypes) {
+                    if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(getContext())) {
+                        filteredTypes.add(compareType);
+                    }
+                }
+            }
+
+            if (filteredTypes.isEmpty()) {
+                for (ExecutableTypeData compareType : otherTypes) {
+                    if (compareType.getType().isGeneric()) {
+                        filteredTypes.add(compareType);
+                    }
+                }
+            }
+
+            return filteredTypes;
+        }
+
+        private CodeTree createFunctionalExecute(CodeTreeBuilder parent, final SpecializationData specialization, final ExecutableTypeData executable) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            if (specialization.isUninitialized()) {
+                builder.tree(createDeoptimize(builder));
+            }
+
+            builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null));
+
+            CodeTree returnSpecialized = null;
+
+            if (specialization.findNextSpecialization() != null) {
+                CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder);
+                returnBuilder.tree(createDeoptimize(builder));
+                returnBuilder.tree(createCallRewriteMonomorphic(builder, executable.hasUnexpectedValue(context), executable.getType(), specialization, null,
+                                "One of guards " + specialization.getGuards() + " failed"));
+                returnSpecialized = returnBuilder.getRoot();
+            }
+
+            builder.tree(createExecuteTree(builder, specialization, SpecializationGroup.create(specialization), new CodeBlock<SpecializationData>() {
+
+                public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
+                    return createExecute(b, executable, specialization);
+                }
+            }, returnSpecialized, false, false, false, false));
+
+            return builder.getRoot();
+        }
+
+        private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            if (!specialization.getExceptions().isEmpty() || !specialization.getAssumptions().isEmpty()) {
+                builder.startTryBlock();
+            }
+
+            for (String assumption : specialization.getAssumptions()) {
+                builder.startStatement();
+                builder.string("this.").string(assumption).string(".check()");
+                builder.end();
+            }
+
+            CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent);
+            if (specialization.isPolymorphic()) {
+                returnBuilder.startCall("next0", EXECUTE_CHAINED);
+                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null);
+                returnBuilder.end();
+            } else if (specialization.isUninitialized()) {
+                returnBuilder.startCall(EXECUTE_UNINITIALIZED);
+                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null);
+                returnBuilder.end();
+            } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
+                emitEncounteredSynthetic(builder, specialization);
+            } else {
+                returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null));
+            }
+
+            if (!returnBuilder.isEmpty()) {
+                TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType());
+                TypeData sourceType = specialization.getReturnType().getTypeSystemType();
+
+                builder.startReturn();
+                if (targetType == null || sourceType == null) {
+                    builder.tree(returnBuilder.getRoot());
+                } else if (sourceType.needsCastTo(targetType)) {
+                    String castMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType);
+                    if (!executable.hasUnexpectedValue(context)) {
+                        castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
+                    }
+                    builder.tree(createCallTypeSystemMethod(parent, node, castMethodName, returnBuilder.getRoot()));
+                } else {
+                    builder.tree(returnBuilder.getRoot());
+                }
+                builder.end();
+            }
+
+            if (!specialization.getExceptions().isEmpty()) {
+                for (SpecializationThrowsData exception : specialization.getExceptions()) {
+                    builder.end().startCatchBlock(exception.getJavaClass(), "ex");
+                    builder.tree(createDeoptimize(builder));
+                    builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), specialization, null,
+                                    "Thrown " + ElementUtils.getSimpleName(exception.getJavaClass())));
+                }
+                builder.end();
+            }
+            if (!specialization.getAssumptions().isEmpty()) {
+                builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex");
+                builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), specialization, null, "Assumption failed"));
+                builder.end();
+            }
+
+            return builder.getRoot();
+        }
+
+        protected CodeExecutableElement createCopyConstructorFactoryMethod(TypeMirror baseType, SpecializationData specialization) {
+            List<Parameter> implicitTypeParams = getImplicitTypeParameters(specialization);
+            String baseName = "current";
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), FACTORY_METHOD_NAME);
+            method.addParameter(new CodeVariableElement(specialization.getNode().getNodeType(), baseName));
+            for (Parameter implicitTypeParam : implicitTypeParams) {
+                method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(implicitTypeParam)));
+            }
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startReturn();
+            builder.startNew(getElement().asType());
+            builder.startGroup().cast(baseType, CodeTreeBuilder.singleString(baseName)).end();
+            for (Parameter param : implicitTypeParams) {
+                builder.string(implicitTypeName(param));
+            }
+            builder.end().end();
+            return method;
+        }
+
+        protected CodeExecutableElement createConstructorFactoryMethod(SpecializationData specialization, ExecutableElement constructor) {
+            List<? extends VariableElement> parameters = constructor.getParameters();
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), FACTORY_METHOD_NAME,
+                            parameters.toArray(new CodeVariableElement[parameters.size()]));
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startReturn();
+            builder.startNew(getElement().asType());
+            for (VariableElement param : parameters) {
+                builder.string(((CodeVariableElement) param).getName());
+            }
+            builder.end().end();
+            return method;
+        }
+    }
+
+    private interface CodeBlock<T> {
+
+        CodeTree create(CodeTreeBuilder parent, T value);
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class TypeSystemCodeGenerator extends AbstractCompilationUnitFactory<TypeSystemData> {
+
+    public static String isTypeMethodName(TypeData type) {
+        return "is" + ElementUtils.getTypeId(type.getBoxedType());
+    }
+
+    public static String isImplicitTypeMethodName(TypeData type) {
+        return "isImplicit" + ElementUtils.getTypeId(type.getBoxedType());
+    }
+
+    public static String asTypeMethodName(TypeData type) {
+        return "as" + ElementUtils.getTypeId(type.getBoxedType());
+    }
+
+    public static String asImplicitTypeMethodName(TypeData type) {
+        return "asImplicit" + ElementUtils.getTypeId(type.getBoxedType());
+    }
+
+    public static String getImplicitClass(TypeData type) {
+        return "getImplicit" + ElementUtils.getTypeId(type.getBoxedType()) + "Class";
+    }
+
+    public static String expectTypeMethodName(TypeData type) {
+        return "expect" + ElementUtils.getTypeId(type.getBoxedType());
+    }
+
+    public static String typeName(TypeSystemData typeSystem) {
+        String name = getSimpleName(typeSystem.getTemplateType());
+        return name + "Gen";
+    }
+
+    public static String singletonName(TypeSystemData type) {
+        return createConstantName(getSimpleName(type.getTemplateType().asType()));
+    }
+
+    @Override
+    protected void createChildren(TypeSystemData m) {
+        add(new TypeClassFactory(), m);
+    }
+
+    private static class TypeClassFactory extends AbstractClassElementFactory<TypeSystemData> {
+
+        private static final String LOCAL_VALUE = "value";
+
+        @Override
+        public CodeTypeElement create(TypeSystemData typeSystem) {
+            String name = typeName(typeSystem);
+            CodeTypeElement clazz = createClass(typeSystem, modifiers(PUBLIC, FINAL), name, typeSystem.getTemplateType().asType(), false);
+
+            clazz.add(createConstructorUsingFields(modifiers(PROTECTED), clazz));
+            CodeVariableElement singleton = createSingleton(clazz);
+            clazz.add(singleton);
+
+            for (TypeData type : typeSystem.getTypes()) {
+                if (!type.isGeneric()) {
+                    clazz.addOptional(createIsTypeMethod(type));
+                    clazz.addOptional(createAsTypeMethod(type));
+
+                    for (TypeData sourceType : collectExpectSourceTypes(type)) {
+                        clazz.addOptional(createExpectTypeMethod(type, sourceType));
+                    }
+
+                    clazz.addOptional(createAsImplicitTypeMethod(type, true));
+                    clazz.addOptional(createAsImplicitTypeMethod(type, false));
+                    clazz.addOptional(createIsImplicitTypeMethod(type, true));
+                    clazz.addOptional(createIsImplicitTypeMethod(type, false));
+                    clazz.addOptional(createGetTypeIndex(type));
+                }
+            }
+
+            return clazz;
+        }
+
+        private static List<TypeData> collectExpectSourceTypes(TypeData type) {
+            Set<TypeData> sourceTypes = new HashSet<>();
+            sourceTypes.add(type.getTypeSystem().getGenericTypeData());
+            for (TypeCastData cast : type.getTypeCasts()) {
+                sourceTypes.add(cast.getSourceType());
+            }
+            for (TypeCheckData cast : type.getTypeChecks()) {
+                sourceTypes.add(cast.getCheckedType());
+            }
+            return new ArrayList<>(sourceTypes);
+        }
+
+        private CodeVariableElement createSingleton(CodeTypeElement clazz) {
+            CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(getModel()));
+            field.createInitBuilder().startNew(clazz.asType()).end();
+            return field;
+        }
+
+        private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) {
+            TypeSystemData typeSystem = getModel();
+            List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
+            if (casts.isEmpty()) {
+                return null;
+            }
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type));
+            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
+            if (typed) {
+                method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint"));
+            }
+            CodeTreeBuilder builder = method.createBuilder();
+
+            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
+
+            builder.startReturn();
+            String sep = "";
+            for (TypeData sourceType : sourceTypes) {
+                builder.string(sep);
+                if (typed) {
+                    builder.string("(typeHint == ").typeLiteral(sourceType.getPrimitiveType()).string(" && ");
+                }
+                builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end();
+                if (typed) {
+                    builder.string(")");
+                }
+                if (sourceTypes.lastIndexOf(sourceType) != sourceTypes.size() - 1) {
+                    builder.newLine();
+                }
+                if (sep.equals("")) {
+                    builder.startIndention();
+                }
+                sep = " || ";
+            }
+            builder.end();
+            builder.end();
+            return method;
+        }
+
+        private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean typed) {
+            TypeSystemData typeSystem = getModel();
+            List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
+            if (casts.isEmpty()) {
+                return null;
+            }
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asImplicitTypeMethodName(type));
+            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
+            if (typed) {
+                method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint"));
+            }
+
+            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
+
+            CodeTreeBuilder builder = method.createBuilder();
+            boolean elseIf = false;
+            for (TypeData sourceType : sourceTypes) {
+                elseIf = builder.startIf(elseIf);
+                if (typed) {
+                    builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType());
+                } else {
+                    builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end();
+                }
+
+                builder.end().startBlock();
+
+                builder.startReturn();
+                ImplicitCastData cast = typeSystem.lookupCast(sourceType, type);
+                if (cast != null) {
+                    builder.startCall(cast.getMethodName());
+                }
+                builder.startCall(asTypeMethodName(sourceType)).string(LOCAL_VALUE).end();
+                if (cast != null) {
+                    builder.end();
+                }
+                builder.end();
+                builder.end();
+            }
+
+            builder.startElseBlock();
+            builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
+            builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
+            builder.end();
+            return method;
+        }
+
+        private CodeExecutableElement createGetTypeIndex(TypeData type) {
+            TypeSystemData typeSystem = getModel();
+            List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
+            if (casts.isEmpty()) {
+                return null;
+            }
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(type));
+            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
+
+            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
+            CodeTreeBuilder builder = method.createBuilder();
+            boolean elseIf = false;
+            for (TypeData sourceType : sourceTypes) {
+                elseIf = builder.startIf(elseIf);
+                builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end();
+                builder.end().startBlock();
+                builder.startReturn().typeLiteral(sourceType.getPrimitiveType()).end();
+                builder.end();
+            }
+
+            builder.startElseBlock();
+            builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
+            builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
+            builder.end();
+
+            return method;
+        }
+
+        private CodeExecutableElement createIsTypeMethod(TypeData type) {
+            if (!type.getTypeChecks().isEmpty()) {
+                return null;
+            }
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(type));
+            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
+
+            DeclaredType suppressWarnings = (DeclaredType) getContext().getType(SuppressWarnings.class);
+            CodeAnnotationMirror annotationMirror = new CodeAnnotationMirror(suppressWarnings);
+            annotationMirror.setElementValue(annotationMirror.findExecutableElement("value"), new CodeAnnotationValue("static-method"));
+            method.getAnnotationMirrors().add(annotationMirror);
+
+            CodeTreeBuilder body = method.createBuilder();
+            body.startReturn().instanceOf(LOCAL_VALUE, type.getBoxedType()).end();
+
+            return method;
+        }
+
+        private CodeExecutableElement createAsTypeMethod(TypeData type) {
+            if (!type.getTypeCasts().isEmpty()) {
+                return null;
+            }
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asTypeMethodName(type));
+            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
+
+            CodeTreeBuilder body = method.createBuilder();
+            String assertMessage = typeName(getModel()) + "." + asTypeMethodName(type) + ": " + ElementUtils.getSimpleName(type.getBoxedType()) + " expected";
+            body.startAssert().startCall(isTypeMethodName(type)).string(LOCAL_VALUE).end().string(" : ").doubleQuote(assertMessage).end();
+            body.startReturn().cast(type.getPrimitiveType(), body.create().string(LOCAL_VALUE).getTree()).end();
+
+            return method;
+        }
+
+        private CodeExecutableElement createExpectTypeMethod(TypeData expectedType, TypeData sourceType) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), expectedType.getPrimitiveType(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType));
+            method.addParameter(new CodeVariableElement(sourceType.getPrimitiveType(), LOCAL_VALUE));
+            method.addThrownType(getContext().getTruffleTypes().getUnexpectedValueException());
+
+            CodeTreeBuilder body = method.createBuilder();
+            body.startIf().startCall(TypeSystemCodeGenerator.isTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end().startBlock();
+            body.startReturn().startCall(TypeSystemCodeGenerator.asTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end();
+            body.end(); // if-block
+            body.startThrow().startNew(getContext().getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end();
+
+            return method;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,946 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+public class ElementUtils {
+
+    public static ExecutableElement findExecutableElement(DeclaredType type, String name) {
+        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements());
+        for (ExecutableElement executableElement : elements) {
+            if (executableElement.getSimpleName().toString().equals(name)) {
+                return executableElement;
+            }
+        }
+        return null;
+    }
+
+    public static boolean needsCastTo(TypeMirror sourceType, TypeMirror targetType) {
+        if (typeEquals(sourceType, targetType)) {
+            return false;
+        } else if (isObject(targetType)) {
+            return false;
+        } else if (isVoid(targetType)) {
+            return false;
+        } else if (isAssignable(sourceType, targetType)) {
+            return false;
+        }
+        return true;
+    }
+
+    public static VariableElement findVariableElement(DeclaredType type, String name) {
+        List<? extends VariableElement> elements = ElementFilter.fieldsIn(type.asElement().getEnclosedElements());
+        for (VariableElement variableElement : elements) {
+            if (variableElement.getSimpleName().toString().equals(name)) {
+                return variableElement;
+            }
+        }
+        return null;
+    }
+
+    public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) {
+        TypeMirror boxedType = primitiveType;
+        if (boxedType.getKind().isPrimitive()) {
+            boxedType = context.getEnvironment().getTypeUtils().boxedClass((PrimitiveType) boxedType).asType();
+        }
+        return boxedType;
+    }
+
+    public static DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) {
+        return new DeclaredCodeTypeMirror(typeElem, Arrays.asList(typeArgs));
+    }
+
+    public static List<AnnotationMirror> collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element,
+                    Class<? extends Annotation> annotationClass) {
+        List<AnnotationMirror> result = new ArrayList<>();
+        if (markerAnnotation != null) {
+            result.addAll(ElementUtils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName));
+        }
+        AnnotationMirror explicit = ElementUtils.findAnnotationMirror(context.getEnvironment(), element, annotationClass);
+        if (explicit != null) {
+            result.add(explicit);
+        }
+        return result;
+    }
+
+    public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror[] types) {
+        if (types.length == 0) {
+            return context.getType(Object.class);
+        }
+        TypeMirror prev = types[0];
+        for (int i = 1; i < types.length; i++) {
+            prev = getCommonSuperType(context, prev, types[i]);
+        }
+        return prev;
+    }
+
+    private static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror type1, TypeMirror type2) {
+        if (typeEquals(type1, type2)) {
+            return type1;
+        }
+        TypeElement element1 = fromTypeMirror(type1);
+        TypeElement element2 = fromTypeMirror(type2);
+        if (element1 == null || element2 == null) {
+            return context.getType(Object.class);
+        }
+
+        List<TypeElement> element1Types = getDirectSuperTypes(element1);
+        element1Types.add(0, element1);
+        List<TypeElement> element2Types = getDirectSuperTypes(element2);
+        element2Types.add(0, element2);
+
+        for (TypeElement superType1 : element1Types) {
+            for (TypeElement superType2 : element2Types) {
+                if (typeEquals(superType1.asType(), superType2.asType())) {
+                    return superType2.asType();
+                }
+            }
+        }
+        return context.getType(Object.class);
+    }
+
+    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:
+            case BYTE:
+            case CHAR:
+            case DOUBLE:
+            case FLOAT:
+            case INT:
+            case SHORT:
+            case LONG:
+            case DECLARED:
+            case VOID:
+            case TYPEVAR:
+                return false;
+            case ARRAY:
+                return hasError(((ArrayType) mirror).getComponentType());
+            case ERROR:
+                return true;
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
+        }
+    }
+
+    public static boolean isSubtype(TypeMirror type1, TypeMirror type2) {
+        if (type1 instanceof CodeTypeMirror && type2 instanceof CodeTypeMirror) {
+            throw new UnsupportedOperationException();
+        }
+        return ProcessorContext.getInstance().getEnvironment().getTypeUtils().isSubtype(type1, type2);
+    }
+
+    public static boolean isAssignable(TypeMirror from, TypeMirror to) {
+        ProcessorContext context = ProcessorContext.getInstance();
+
+        if (!(from instanceof CodeTypeMirror) && !(to instanceof CodeTypeMirror)) {
+            return context.getEnvironment().getTypeUtils().isAssignable(context.reloadType(from), context.reloadType(to));
+        } else {
+            return isAssignableImpl(from, to);
+        }
+    }
+
+    private static boolean isAssignableImpl(TypeMirror from, TypeMirror to) {
+        // JLS 5.1.1 identity conversion
+        if (ElementUtils.typeEquals(from, to)) {
+            return true;
+        }
+
+        if (isObject(to)) {
+            return true;
+        }
+
+        // JLS 5.1.2 widening primitives
+        if (ElementUtils.isPrimitive(from) && ElementUtils.isPrimitive(to)) {
+            TypeKind fromKind = from.getKind();
+            TypeKind toKind = to.getKind();
+            switch (fromKind) {
+                case BYTE:
+                    switch (toKind) {
+                        case SHORT:
+                        case INT:
+                        case LONG:
+                        case FLOAT:
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+                case SHORT:
+                    switch (toKind) {
+                        case INT:
+                        case LONG:
+                        case FLOAT:
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+                case CHAR:
+                    switch (toKind) {
+                        case INT:
+                        case LONG:
+                        case FLOAT:
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+                case INT:
+                    switch (toKind) {
+                        case LONG:
+                        case FLOAT:
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+                case LONG:
+                    switch (toKind) {
+                        case FLOAT:
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+                case FLOAT:
+                    switch (toKind) {
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+
+            }
+            return false;
+        } else if (ElementUtils.isPrimitive(from) || ElementUtils.isPrimitive(to)) {
+            return false;
+        }
+
+        if (from instanceof ArrayType && to instanceof ArrayType) {
+            return isAssignable(((ArrayType) from).getComponentType(), ((ArrayType) to).getComponentType());
+        }
+
+        if (from instanceof ArrayType || to instanceof ArrayType) {
+            return false;
+        }
+
+        TypeElement fromType = ElementUtils.fromTypeMirror(from);
+        TypeElement toType = ElementUtils.fromTypeMirror(to);
+        if (fromType == null || toType == null) {
+            return false;
+        }
+        // JLS 5.1.6 narrowing reference conversion
+
+        List<TypeElement> superTypes = ElementUtils.getSuperTypes(fromType);
+        for (TypeElement superType : superTypes) {
+            if (ElementUtils.typeEquals(superType.asType(), to)) {
+                return true;
+            }
+        }
+
+        // TODO more spec
+        return false;
+    }
+
+    public static Set<Modifier> modifiers(Modifier... modifier) {
+        return new LinkedHashSet<>(Arrays.asList(modifier));
+    }
+
+    public static String getTypeId(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case BOOLEAN:
+                return "Boolean";
+            case BYTE:
+                return "Byte";
+            case CHAR:
+                return "Char";
+            case DOUBLE:
+                return "Double";
+            case FLOAT:
+                return "Float";
+            case SHORT:
+                return "Short";
+            case INT:
+                return "Int";
+            case LONG:
+                return "Long";
+            case DECLARED:
+                return fixECJBinaryNameIssue(((DeclaredType) mirror).asElement().getSimpleName().toString());
+            case ARRAY:
+                return getTypeId(((ArrayType) mirror).getComponentType()) + "Array";
+            case VOID:
+                return "Void";
+            case WILDCARD:
+                StringBuilder b = new StringBuilder();
+                WildcardType type = (WildcardType) mirror;
+                if (type.getExtendsBound() != null) {
+                    b.append("Extends").append(getTypeId(type.getExtendsBound()));
+                } else if (type.getSuperBound() != null) {
+                    b.append("Super").append(getTypeId(type.getExtendsBound()));
+                }
+                return b.toString();
+            case TYPEVAR:
+                return "Any";
+            case ERROR:
+                throw new CompileErrorException("Type error " + mirror);
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
+        }
+    }
+
+    public static String getSimpleName(TypeElement element) {
+        return getSimpleName(element.asType());
+    }
+
+    public static String getSimpleName(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case BOOLEAN:
+                return "boolean";
+            case BYTE:
+                return "byte";
+            case CHAR:
+                return "char";
+            case DOUBLE:
+                return "double";
+            case FLOAT:
+                return "float";
+            case SHORT:
+                return "short";
+            case INT:
+                return "int";
+            case LONG:
+                return "long";
+            case DECLARED:
+                return getDeclaredName((DeclaredType) mirror);
+            case ARRAY:
+                return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]";
+            case VOID:
+                return "void";
+            case WILDCARD:
+                return getWildcardName((WildcardType) mirror);
+            case TYPEVAR:
+                return "?";
+            case ERROR:
+                throw new CompileErrorException("Type error " + mirror);
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
+        }
+    }
+
+    private static String getWildcardName(WildcardType type) {
+        StringBuilder b = new StringBuilder();
+        if (type.getExtendsBound() != null) {
+            b.append("? extends ").append(getSimpleName(type.getExtendsBound()));
+        } else if (type.getSuperBound() != null) {
+            b.append("? super ").append(getSimpleName(type.getExtendsBound()));
+        }
+        return b.toString();
+    }
+
+    private static String getDeclaredName(DeclaredType element) {
+        String simpleName = fixECJBinaryNameIssue(element.asElement().getSimpleName().toString());
+
+        if (element.getTypeArguments().size() == 0) {
+            return simpleName;
+        }
+
+        StringBuilder b = new StringBuilder(simpleName);
+        b.append("<");
+        if (element.getTypeArguments().size() > 0) {
+            for (int i = 0; i < element.getTypeArguments().size(); i++) {
+                b.append(getSimpleName(element.getTypeArguments().get(i)));
+                if (i < element.getTypeArguments().size() - 1) {
+                    b.append(", ");
+                }
+            }
+        }
+        b.append(">");
+        return b.toString();
+    }
+
+    public static String fixECJBinaryNameIssue(String name) {
+        if (name.contains("$")) {
+            int lastIndex = name.lastIndexOf('$');
+            return name.substring(lastIndex + 1, name.length());
+        }
+        return name;
+    }
+
+    public static String getQualifiedName(TypeElement element) {
+        String qualifiedName = element.getQualifiedName().toString();
+        if (qualifiedName.contains("$")) {
+            /*
+             * If a class gets loaded in its binary form by the ECJ compiler it fails to produce the
+             * proper canonical class name. It leaves the $ in the qualified name of the class. So
+             * one instance of a TypeElement may be loaded in binary and one in source form. The
+             * current type comparison in #typeEquals compares by the qualified name so the
+             * qualified name must match. This is basically a hack to fix the returned qualified
+             * name of eclipse.
+             */
+            qualifiedName = qualifiedName.replace('$', '.');
+        }
+        return qualifiedName;
+    }
+
+    public static String getQualifiedName(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case BOOLEAN:
+                return "boolean";
+            case BYTE:
+                return "byte";
+            case CHAR:
+                return "char";
+            case DOUBLE:
+                return "double";
+            case SHORT:
+                return "short";
+            case FLOAT:
+                return "float";
+            case INT:
+                return "int";
+            case LONG:
+                return "long";
+            case DECLARED:
+                return getQualifiedName(fromTypeMirror(mirror));
+            case ARRAY:
+                return getQualifiedName(((ArrayType) mirror).getComponentType());
+            case VOID:
+                return "void";
+            case TYPEVAR:
+                return getSimpleName(mirror);
+            case ERROR:
+                throw new CompileErrorException("Type error " + mirror);
+            case EXECUTABLE:
+                return ((ExecutableType) mirror).toString();
+            case NONE:
+                return "$none";
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror);
+        }
+    }
+
+    public static boolean isVoid(TypeMirror mirror) {
+        return mirror != null && mirror.getKind() == TypeKind.VOID;
+    }
+
+    public static boolean isPrimitive(TypeMirror mirror) {
+        return mirror != null && mirror.getKind().isPrimitive();
+    }
+
+    public static List<String> getQualifiedSuperTypeNames(TypeElement element) {
+        List<TypeElement> types = getSuperTypes(element);
+        List<String> qualifiedNames = new ArrayList<>();
+        for (TypeElement type : types) {
+            qualifiedNames.add(getQualifiedName(type));
+        }
+        return qualifiedNames;
+    }
+
+    public static List<TypeElement> getDeclaredTypes(TypeElement element) {
+        return ElementFilter.typesIn(element.getEnclosedElements());
+    }
+
+    public static boolean isEnclosedIn(Element enclosedIn, Element element) {
+        if (element == null) {
+            return false;
+        } else if (enclosedIn.equals(element)) {
+            return true;
+        } else {
+            return isEnclosedIn(enclosedIn, 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 null;
+    }
+
+    public 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> getDirectSuperTypes(TypeElement element) {
+        List<TypeElement> types = new ArrayList<>();
+        if (element.getSuperclass() != null) {
+            TypeElement superElement = fromTypeMirror(element.getSuperclass());
+            if (superElement != null) {
+                types.add(superElement);
+                types.addAll(getDirectSuperTypes(superElement));
+            }
+        }
+
+        return types;
+    }
+
+    public static List<TypeMirror> getAssignableTypes(ProcessorContext context, TypeMirror type) {
+        if (isPrimitive(type)) {
+            return Arrays.asList(type, boxType(context, type), context.getType(Object.class));
+        } else if (type.getKind() == TypeKind.ARRAY) {
+            return Arrays.asList(type, context.getType(Object.class));
+        } else if (type.getKind() == TypeKind.DECLARED) {
+            List<TypeElement> types = getSuperTypes(fromTypeMirror(type));
+            List<TypeMirror> mirrors = new ArrayList<>(types.size());
+            mirrors.add(type);
+            for (TypeElement typeElement : types) {
+                mirrors.add(typeElement.asType());
+            }
+            return mirrors;
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+    public static List<TypeElement> getSuperTypes(TypeElement element) {
+        List<TypeElement> types = new ArrayList<>();
+        List<TypeElement> superTypes = null;
+        List<TypeElement> superInterfaces = null;
+        if (element.getSuperclass() != null) {
+            TypeElement superElement = fromTypeMirror(element.getSuperclass());
+            if (superElement != null) {
+                types.add(superElement);
+                superTypes = getSuperTypes(superElement);
+            }
+        }
+        for (TypeMirror interfaceMirror : element.getInterfaces()) {
+            TypeElement interfaceElement = fromTypeMirror(interfaceMirror);
+            if (interfaceElement != null) {
+                types.add(interfaceElement);
+                superInterfaces = getSuperTypes(interfaceElement);
+            }
+        }
+
+        if (superTypes != null) {
+            types.addAll(superTypes);
+        }
+
+        if (superInterfaces != null) {
+            types.addAll(superInterfaces);
+        }
+
+        return types;
+    }
+
+    public static String getPackageName(TypeElement element) {
+        return findPackageElement(element).getQualifiedName().toString();
+    }
+
+    public static String getPackageName(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case BOOLEAN:
+            case BYTE:
+            case CHAR:
+            case DOUBLE:
+            case FLOAT:
+            case SHORT:
+            case INT:
+            case LONG:
+            case VOID:
+            case TYPEVAR:
+                return null;
+            case DECLARED:
+                PackageElement pack = findPackageElement(fromTypeMirror(mirror));
+                if (pack == null) {
+                    throw new IllegalArgumentException("No package element found for declared type " + getSimpleName(mirror));
+                }
+                return pack.getQualifiedName().toString();
+            case ARRAY:
+                return getSimpleName(((ArrayType) mirror).getComponentType());
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror.getKind());
+        }
+    }
+
+    public static String createConstantName(String simpleName) {
+        // TODO use camel case to produce underscores.
+        return simpleName.toString().toUpperCase();
+    }
+
+    public static TypeElement fromTypeMirror(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case DECLARED:
+                return (TypeElement) ((DeclaredType) mirror).asElement();
+            case ARRAY:
+                return fromTypeMirror(((ArrayType) mirror).getComponentType());
+            default:
+                return null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> List<T> getAnnotationValueList(Class<T> expectedListType, AnnotationMirror mirror, String name) {
+        List<? extends AnnotationValue> values = getAnnotationValue(List.class, mirror, name);
+        List<T> result = new ArrayList<>();
+
+        if (values != null) {
+            for (AnnotationValue value : values) {
+                T annotationValue = resolveAnnotationValue(expectedListType, value);
+                if (annotationValue != null) {
+                    result.add(annotationValue);
+                }
+            }
+        }
+        return result;
+    }
+
+    public static <T> T getAnnotationValue(Class<T> expectedType, AnnotationMirror mirror, String name) {
+        return resolveAnnotationValue(expectedType, getAnnotationValue(mirror, name));
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private static <T> T resolveAnnotationValue(Class<T> expectedType, AnnotationValue value) {
+        if (value == null) {
+            return null;
+        }
+
+        Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null);
+        if (unboxedValue != null) {
+            if (expectedType == TypeMirror.class && unboxedValue instanceof String) {
+                return null;
+            }
+            if (!expectedType.isAssignableFrom(unboxedValue.getClass())) {
+                throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName());
+            }
+        }
+        return (T) unboxedValue;
+    }
+
+    public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) {
+        ExecutableElement valueMethod = null;
+        for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) {
+            if (method.getSimpleName().toString().equals(name)) {
+                valueMethod = method;
+                break;
+            }
+        }
+
+        if (valueMethod == null) {
+            return null;
+        }
+
+        AnnotationValue value = mirror.getElementValues().get(valueMethod);
+        if (value == null) {
+            value = valueMethod.getDefaultValue();
+        }
+
+        return value;
+    }
+
+    private static class AnnotationValueVisitorImpl extends AbstractAnnotationValueVisitor7<Object, Void> {
+
+        @Override
+        public Object visitBoolean(boolean b, Void p) {
+            return Boolean.valueOf(b);
+        }
+
+        @Override
+        public Object visitByte(byte b, Void p) {
+            return Byte.valueOf(b);
+        }
+
+        @Override
+        public Object visitChar(char c, Void p) {
+            return c;
+        }
+
+        @Override
+        public Object visitDouble(double d, Void p) {
+            return d;
+        }
+
+        @Override
+        public Object visitFloat(float f, Void p) {
+            return f;
+        }
+
+        @Override
+        public Object visitInt(int i, Void p) {
+            return i;
+        }
+
+        @Override
+        public Object visitLong(long i, Void p) {
+            return i;
+        }
+
+        @Override
+        public Object visitShort(short s, Void p) {
+            return s;
+        }
+
+        @Override
+        public Object visitString(String s, Void p) {
+            return s;
+        }
+
+        @Override
+        public Object visitType(TypeMirror t, Void p) {
+            return t;
+        }
+
+        @Override
+        public Object visitEnumConstant(VariableElement c, Void p) {
+            return c;
+        }
+
+        @Override
+        public Object visitAnnotation(AnnotationMirror a, Void p) {
+            return a;
+        }
+
+        @Override
+        public Object visitArray(List<? extends AnnotationValue> vals, Void p) {
+            return vals;
+        }
+
+    }
+
+    public static String printException(Throwable e) {
+        StringWriter string = new StringWriter();
+        PrintWriter writer = new PrintWriter(string);
+        e.printStackTrace(writer);
+        writer.flush();
+        return e.getMessage() + "\r\n" + string.toString();
+    }
+
+    public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, Element element, Class<?> annotationClass) {
+        return findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), annotationClass);
+    }
+
+    public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List<? extends AnnotationMirror> mirrors, Class<?> annotationClass) {
+        TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName());
+        return findAnnotationMirror(mirrors, expectedAnnotationType);
+    }
+
+    public static AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> mirrors, TypeElement expectedAnnotationType) {
+        for (AnnotationMirror mirror : mirrors) {
+            DeclaredType annotationType = mirror.getAnnotationType();
+            TypeElement actualAnnotationType = (TypeElement) annotationType.asElement();
+            if (actualAnnotationType.equals(expectedAnnotationType)) {
+                return mirror;
+            }
+        }
+        return null;
+    }
+
+    private static PackageElement findPackageElement(Element type) {
+        List<Element> hierarchy = getElementHierarchy(type);
+        for (Element element : hierarchy) {
+            if (element.getKind() == ElementKind.PACKAGE) {
+                return (PackageElement) element;
+            }
+        }
+        return null;
+    }
+
+    public static String firstLetterUpperCase(String name) {
+        if (name == null || name.isEmpty()) {
+            return name;
+        }
+        return Character.toUpperCase(name.charAt(0)) + name.substring(1, name.length());
+    }
+
+    public static String firstLetterLowerCase(String name) {
+        if (name == null || name.isEmpty()) {
+            return name;
+        }
+        return Character.toLowerCase(name.charAt(0)) + name.substring(1, name.length());
+    }
+
+    private static ExecutableElement getDeclaredMethod(TypeElement element, String name, TypeMirror[] params) {
+        List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements());
+        method: for (ExecutableElement method : methods) {
+            if (!method.getSimpleName().toString().equals(name)) {
+                continue;
+            }
+            if (method.getParameters().size() != params.length) {
+                continue;
+            }
+            for (int i = 0; i < params.length; i++) {
+                TypeMirror param1 = params[i];
+                TypeMirror param2 = method.getParameters().get(i).asType();
+                if (param1.getKind() != TypeKind.TYPEVAR && param2.getKind() != TypeKind.TYPEVAR) {
+                    if (!getQualifiedName(param1).equals(getQualifiedName(param2))) {
+                        continue method;
+                    }
+                }
+            }
+            return method;
+        }
+        return null;
+    }
+
+    private static boolean isDeclaredMethod(TypeElement element, String name, TypeMirror[] params) {
+        return getDeclaredMethod(element, name, params) != null;
+    }
+
+    public static boolean isDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) {
+        List<TypeElement> superElements = getSuperTypes(element);
+
+        for (TypeElement typeElement : superElements) {
+            if (isDeclaredMethod(typeElement, name, params)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean typeEquals(TypeMirror type1, TypeMirror type2) {
+        if (type1 == null && type2 == null) {
+            return true;
+        } else if (type1 == null || type2 == null) {
+            return false;
+        } else if (type1 == type2) {
+            return true;
+        }
+        String qualified1 = getQualifiedName(type1);
+        String qualified2 = getQualifiedName(type2);
+
+        if (type1.getKind() == TypeKind.ARRAY || type2.getKind() == TypeKind.ARRAY) {
+            if (type1.getKind() == TypeKind.ARRAY && type2.getKind() == TypeKind.ARRAY) {
+                return typeEquals(((ArrayType) type1).getComponentType(), ((ArrayType) type2).getComponentType());
+            } else {
+                return false;
+            }
+        }
+        return qualified1.equals(qualified2);
+    }
+
+    public static int compareByTypeHierarchy(TypeMirror t1, TypeMirror t2) {
+        if (typeEquals(t1, t2)) {
+            return 0;
+        }
+        Set<String> t1SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t1)));
+        if (t1SuperSet.contains(getQualifiedName(t2))) {
+            return -1;
+        }
+
+        Set<String> t2SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t2)));
+        if (t2SuperSet.contains(getQualifiedName(t1))) {
+            return 1;
+        }
+        return 0;
+    }
+
+    public static boolean canThrowType(List<? extends TypeMirror> thrownTypes, TypeMirror exceptionType) {
+        if (ElementUtils.containsType(thrownTypes, exceptionType)) {
+            return true;
+        }
+
+        if (isRuntimeException(exceptionType)) {
+            return true;
+        }
+
+        // search for any super types
+        TypeElement exceptionTypeElement = fromTypeMirror(exceptionType);
+        List<TypeElement> superTypes = getSuperTypes(exceptionTypeElement);
+        for (TypeElement typeElement : superTypes) {
+            if (ElementUtils.containsType(thrownTypes, typeElement.asType())) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public static Modifier getVisibility(Set<Modifier> modifier) {
+        for (Modifier mod : modifier) {
+            if (mod == Modifier.PUBLIC || mod == Modifier.PRIVATE || 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);
+        if (!typeSuperSet.contains(Throwable.class.getCanonicalName()) && !typeName.equals(Throwable.class.getCanonicalName())) {
+            throw new IllegalArgumentException("Given type does not extend Throwable.");
+        }
+        return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || typeName.equals(RuntimeException.class.getCanonicalName());
+    }
+
+    private static boolean containsType(Collection<? extends TypeMirror> collection, TypeMirror type) {
+        for (TypeMirror otherTypeMirror : collection) {
+            if (typeEquals(otherTypeMirror, type)) {
+                return true;
+            }
+        }
+        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;
+    }
+
+    public static boolean isObject(TypeMirror actualType) {
+        return actualType.getKind() == TypeKind.DECLARED && getQualifiedName(actualType).equals("java.lang.Object");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/AbstractCompiler.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.compiler;
+
+import java.lang.reflect.*;
+
+public abstract class AbstractCompiler implements Compiler {
+
+    protected static Object method(Object o, String methodName) throws Exception {
+        Method method = o.getClass().getMethod(methodName);
+        method.setAccessible(true);
+        return method.invoke(o);
+    }
+
+    protected static Object method(Object o, String methodName, Class<?>[] paramTypes, Object... values) throws Exception {
+        Method method = o.getClass().getMethod(methodName, paramTypes);
+        method.setAccessible(true);
+        return method.invoke(o, values);
+    }
+
+    protected static Object field(Object o, String fieldName) throws Exception {
+        if (o == null) {
+            return null;
+        }
+        Class<?> clazz = o.getClass();
+        Field field = null;
+        try {
+            field = clazz.getField(fieldName);
+        } catch (NoSuchFieldException e) {
+            while (clazz != null) {
+                try {
+                    field = clazz.getDeclaredField(fieldName);
+                    break;
+                } catch (NoSuchFieldException e1) {
+                    clazz = clazz.getSuperclass();
+                }
+            }
+            if (field == null) {
+                throw e;
+            }
+        }
+        field.setAccessible(true);
+        return field.get(o);
+    }
+
+    protected static String parseHeader(String content) {
+        int index = content.indexOf("/*");
+        if (index == -1) {
+            return null;
+        }
+        if (!content.substring(0, index).trim().equals("")) {
+            // just whitespace before
+            return null;
+        }
+
+        int endIndex = content.indexOf("*/", index);
+        if (endIndex == -1) {
+            return null;
+        }
+        return content.substring(index, endIndex + 2);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/Compiler.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.compiler;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+
+public interface Compiler {
+
+    String getMethodBody(ProcessingEnvironment env, ExecutableElement method);
+
+    String getHeaderComment(ProcessingEnvironment env, Element type);
+
+    List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type);
+
+    List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/CompilerFactory.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.compiler;
+
+import javax.lang.model.element.*;
+
+public class CompilerFactory {
+
+    private static Compiler javac;
+    private static Compiler jdt;
+
+    public static Compiler getCompiler(Element currentElement) {
+        if (JavaCCompiler.isValidElement(currentElement)) {
+            if (javac == null) {
+                javac = new JavaCCompiler();
+            }
+            return javac;
+        } else if (JDTCompiler.isValidElement(currentElement)) {
+            if (jdt == null) {
+                jdt = new JDTCompiler();
+            }
+            return jdt;
+        } else {
+            throw new UnsupportedOperationException("Unsupported compiler for element " + currentElement.getClass().getName() + ".");
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.compiler;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class JDTCompiler extends AbstractCompiler {
+
+    public static boolean isValidElement(Element currentElement) {
+        try {
+            Class<?> elementClass = Class.forName("org.eclipse.jdt.internal.compiler.apt.model.ElementImpl");
+            return elementClass.isAssignableFrom(currentElement.getClass());
+        } catch (ClassNotFoundException e) {
+            return false;
+        }
+    }
+
+    public List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) {
+        return sortBySourceOrder(new ArrayList<>(environment.getElementUtils().getAllMembers(type)));
+    }
+
+    public List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type) {
+        return sortBySourceOrder(new ArrayList<>(type.getEnclosedElements()));
+    }
+
+    private static List<? extends Element> sortBySourceOrder(List<Element> elements) {
+        final Map<TypeElement, List<Object>> declarationOrders = new HashMap<>();
+
+        Collections.sort(elements, new Comparator<Element>() {
+            public int compare(Element o1, Element o2) {
+                try {
+                    TypeMirror enclosing1 = o1.getEnclosingElement().asType();
+                    TypeMirror enclosing2 = o2.getEnclosingElement().asType();
+
+                    if (ElementUtils.typeEquals(enclosing1, enclosing2)) {
+                        List<Object> declarationOrder = lookupDeclarationOrder(declarationOrders, (TypeElement) o1.getEnclosingElement());
+                        if (declarationOrder == null) {
+                            return 0;
+                        }
+                        Object o1Binding = field(o1, "_binding");
+                        Object o2Binding = field(o2, "_binding");
+
+                        int i1 = declarationOrder.indexOf(o1Binding);
+                        int i2 = declarationOrder.indexOf(o2Binding);
+
+                        return i1 - i2;
+                    } else {
+                        if (ElementUtils.isSubtype(enclosing1, enclosing2)) {
+                            return 1;
+                        } else if (ElementUtils.isSubtype(enclosing2, enclosing1)) {
+                            return -1;
+                        } else {
+                            return 0;
+                        }
+                    }
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+        return elements;
+    }
+
+    private static List<Object> lookupDeclarationOrder(Map<TypeElement, List<Object>> declarationOrders, TypeElement type) throws Exception, ClassNotFoundException {
+        if (declarationOrders.containsKey(type)) {
+            return declarationOrders.get(type);
+        }
+
+        Object binding = field(type, "_binding");
+        Class<?> sourceTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding");
+        Class<?> binaryTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding");
+
+        List<Object> declarationOrder = null;
+        if (sourceTypeBinding.isAssignableFrom(binding.getClass())) {
+            declarationOrder = findSourceTypeOrder(binding);
+        } else if (binaryTypeBinding.isAssignableFrom(binding.getClass())) {
+            declarationOrder = findBinaryTypeOrder(binding);
+        }
+
+        declarationOrders.put(type, declarationOrder);
+
+        return declarationOrder;
+    }
+
+    private static List<Object> findBinaryTypeOrder(Object binding) throws Exception {
+        Object binaryType = lookupBinaryType(binding);
+        final Object[] sortedMethods = (Object[]) method(binaryType, "getMethods");
+
+        List<Object> sortedElements = new ArrayList<>();
+        if (sortedMethods != null) {
+            sortedElements.addAll(Arrays.asList(sortedMethods));
+        }
+        final Object[] sortedFields = (Object[]) method(binaryType, "getFields");
+        if (sortedFields != null) {
+            sortedElements.addAll(Arrays.asList(sortedFields));
+        }
+        final Object[] sortedTypes = (Object[]) method(binaryType, "getMemberTypes", new Class[0]);
+        if (sortedTypes != null) {
+            sortedElements.addAll(Arrays.asList(sortedTypes));
+        }
+
+        Collections.sort(sortedElements, new Comparator<Object>() {
+            public int compare(Object o1, Object o2) {
+                try {
+                    int structOffset1 = (int) field(o1, "structOffset");
+                    int structOffset2 = (int) field(o2, "structOffset");
+                    return structOffset1 - structOffset2;
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+
+        Class<?> binaryMethod = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryMethod");
+        Class<?> binaryField = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryField");
+        Class<?> nestedType = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryNestedType");
+
+        List<Object> bindings = new ArrayList<>();
+        for (Object sortedElement : sortedElements) {
+            Class<?> elementClass = sortedElement.getClass();
+            if (binaryMethod.isAssignableFrom(elementClass)) {
+                char[] selector = (char[]) method(sortedElement, "getSelector");
+                Object[] foundBindings = (Object[]) method(binding, "getMethods", new Class[]{char[].class}, selector);
+                if (foundBindings == null || foundBindings.length == 0) {
+                    continue;
+                } else if (foundBindings.length == 1) {
+                    bindings.add(foundBindings[0]);
+                } else {
+                    char[] idescriptor = (char[]) method(sortedElement, "getMethodDescriptor");
+                    for (Object foundBinding : foundBindings) {
+                        char[] descriptor = (char[]) method(foundBinding, "signature");
+                        if (descriptor == null && idescriptor == null || Arrays.equals(descriptor, idescriptor)) {
+                            bindings.add(foundBinding);
+                            break;
+                        }
+                    }
+                }
+            } else if (binaryField.isAssignableFrom(elementClass)) {
+                char[] selector = (char[]) method(sortedElement, "getName");
+                Object foundField = method(binding, "getField", new Class[]{char[].class, boolean.class}, selector, true);
+                if (foundField != null) {
+                    bindings.add(foundField);
+                }
+            } else if (nestedType.isAssignableFrom(elementClass)) {
+                char[] selector = (char[]) method(sortedElement, "getSourceName");
+                Object foundType = method(binding, "getMemberType", new Class[]{char[].class}, selector);
+                if (foundType != null) {
+                    bindings.add(foundType);
+                }
+            } else {
+                throw new AssertionError("Unexpected encountered type " + elementClass);
+            }
+        }
+
+        return bindings;
+    }
+
+    private static Object lookupBinaryType(Object binding) throws Exception {
+        Object lookupEnvironment = field(binding, "environment");
+        Object compoundClassName = field(binding, "compoundName");
+        Object nameEnvironment = field(lookupEnvironment, "nameEnvironment");
+        Object nameEnvironmentAnswer = method(nameEnvironment, "findType", new Class[]{char[][].class}, compoundClassName);
+        Object binaryType = method(nameEnvironmentAnswer, "getBinaryType", new Class[0]);
+        return binaryType;
+    }
+
+    private static List<Object> findSourceTypeOrder(Object binding) throws Exception {
+        Object referenceContext = field(field(binding, "scope"), "referenceContext");
+
+        TreeMap<Integer, Object> orderedBindings = new TreeMap<>();
+
+        collectSourceOrder(orderedBindings, referenceContext, "methods");
+        collectSourceOrder(orderedBindings, referenceContext, "fields");
+        collectSourceOrder(orderedBindings, referenceContext, "memberTypes");
+
+        return new ArrayList<>(orderedBindings.values());
+    }
+
+    private static void collectSourceOrder(TreeMap<Integer, Object> orderedBindings, Object referenceContext, String fieldName) throws Exception {
+        Object[] declarations = (Object[]) field(referenceContext, fieldName);
+        if (declarations != null) {
+            for (int i = 0; i < declarations.length; i++) {
+                Integer declarationSourceStart = (Integer) field(declarations[i], "declarationSourceStart");
+                orderedBindings.put(declarationSourceStart, field(declarations[i], "binding"));
+            }
+        }
+    }
+
+    @Override
+    public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
+        try {
+
+            char[] source = getSource(method);
+            if (source == null) {
+                return null;
+            }
+
+            /*
+             * 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");
+
+            int length = bodyEnd - bodyStart;
+            char[] target = new char[length];
+            System.arraycopy(source, bodyStart, target, 0, length);
+
+            return new String(target);
+        } catch (Exception e) {
+            return ElementUtils.printException(e);
+        }
+    }
+
+    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;
+         */
+
+        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");
+
+        char[] source = null;
+        if (methodBindingClass.isAssignableFrom(binding.getClass())) {
+            Object sourceMethod = method(binding, "sourceMethod");
+            if (sourceMethod == null) {
+                return null;
+            }
+            source = (char[]) method(method(field(sourceMethod, "compilationResult"), "getCompilationUnit"), "getContents");
+        } else if (referenceBindingClass.isAssignableFrom(binding.getClass())) {
+            source = (char[]) method(field(field(field(field(binding, "scope"), "referenceContext"), "compilationResult"), "compilationUnit"), "getContents");
+        }
+        return source;
+    }
+
+    @Override
+    public String getHeaderComment(ProcessingEnvironment env, Element type) {
+        try {
+            char[] source = getSource(type);
+            if (source == null) {
+                return null;
+            }
+            return parseHeader(new String(source));
+        } catch (Exception e) {
+            return ElementUtils.printException(e);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JavaCCompiler.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.compiler;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class JavaCCompiler extends AbstractCompiler {
+
+    public static boolean isValidElement(Element currentElement) {
+        try {
+            Class<?> elementClass = Class.forName("com.sun.tools.javac.code.Symbol");
+            return elementClass.isAssignableFrom(currentElement.getClass());
+        } catch (ClassNotFoundException e) {
+            return false;
+        }
+    }
+
+    public List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type) {
+        return type.getEnclosedElements();
+    }
+
+    public List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) {
+        return environment.getElementUtils().getAllMembers(type);
+    }
+
+    private static final Class<?>[] getTreeAndTopLevelSignature = new Class[]{Element.class, AnnotationMirror.class, AnnotationValue.class};
+    private static final Class<?>[] getCharContentSignature = new Class[]{boolean.class};
+
+    @Override
+    public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
+        try {
+            /*
+             * if (false) { Pair<JCTree, JCCompilationUnit> treeAndTopLevel = ((JavacElements)
+             * env.getElementUtils()).getTreeAndTopLevel(method, null, null); JCBlock block =
+             * ((JCMethodDecl) treeAndTopLevel.fst).getBody(); int startPos = block.pos; int endPos
+             * = block.endpos; String methodBody =
+             * treeAndTopLevel.snd.getSourceFile().getCharContent(true).subSequence(startPos + 1,
+             * endPos).toString(); return methodBody; }
+             */
+
+            Object treeAndTopLevel = getTreeAndTopLevel(env, method);
+            Object block = method(field(treeAndTopLevel, "fst"), "getBody");
+            int startPos = (int) field(block, "pos");
+            int endPos = (int) field(block, "endpos");
+            return getContent(treeAndTopLevel).subSequence(startPos + 1, endPos).toString();
+        } catch (Exception e) {
+            return ElementUtils.printException(e);
+        }
+    }
+
+    private static CharSequence getContent(Object treeAndTopLevel) throws Exception {
+        /*
+         * CharSequence content = treeAndTopLevel.snd.getSourceFile().getCharContent(true);
+         */
+        return (CharSequence) method(method(field(treeAndTopLevel, "snd"), "getSourceFile"), "getCharContent", getCharContentSignature, true);
+    }
+
+    private static Object getTreeAndTopLevel(ProcessingEnvironment env, Element element) throws Exception {
+        /*
+         * Pair<JCTree, JCCompilationUnit> treeAndTopLevel = ((JavacElements)
+         * env.getElementUtils()).getTreeAndTopLevel(method, null, null);
+         */
+        return method(method(env, "getElementUtils"), "getTreeAndTopLevel", getTreeAndTopLevelSignature, element, null, null);
+    }
+
+    @Override
+    public String getHeaderComment(ProcessingEnvironment env, Element type) {
+        try {
+            String content = getContent(getTreeAndTopLevel(env, type)).toString();
+            return parseHeader(content);
+        } catch (Exception e) {
+            return ElementUtils.printException(e);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationMirror.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class CodeAnnotationMirror implements AnnotationMirror {
+
+    private final DeclaredType annotationType;
+    private final Map<ExecutableElement, AnnotationValue> values = new LinkedHashMap<>();
+
+    public CodeAnnotationMirror(DeclaredType annotationType) {
+        this.annotationType = annotationType;
+    }
+
+    @Override
+    public DeclaredType getAnnotationType() {
+        return annotationType;
+    }
+
+    @Override
+    public Map<? extends ExecutableElement, ? extends AnnotationValue> getElementValues() {
+        return values;
+    }
+
+    public void setElementValue(ExecutableElement method, AnnotationValue value) {
+        values.put(method, value);
+    }
+
+    public ExecutableElement findExecutableElement(String name) {
+        return ElementUtils.findExecutableElement(annotationType, name);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationValue.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class CodeAnnotationValue implements AnnotationValue {
+
+    private final Object value;
+
+    public CodeAnnotationValue(Object value) {
+        Objects.requireNonNull(value);
+        if ((value instanceof AnnotationMirror) || (value instanceof List<?>) || (value instanceof Boolean) || (value instanceof Byte) || (value instanceof Character) || (value instanceof Double) ||
+                        (value instanceof VariableElement) || (value instanceof Float) || (value instanceof Integer) || (value instanceof Long) || (value instanceof Short) ||
+                        (value instanceof String) || (value instanceof TypeMirror)) {
+            this.value = value;
+        } else {
+            throw new IllegalArgumentException("Invalid annotation value type " + value.getClass().getName());
+        }
+    }
+
+    @Override
+    public Object getValue() {
+        return value;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
+        if (value instanceof AnnotationMirror) {
+            return v.visitAnnotation((AnnotationMirror) value, p);
+        } else if (value instanceof List<?>) {
+            return v.visitArray((List<? extends AnnotationValue>) value, p);
+        } else if (value instanceof Boolean) {
+            return v.visitBoolean((boolean) value, p);
+        } else if (value instanceof Byte) {
+            return v.visitByte((byte) value, p);
+        } else if (value instanceof Character) {
+            return v.visitChar((char) value, p);
+        } else if (value instanceof Double) {
+            return v.visitDouble((double) value, p);
+        } else if (value instanceof VariableElement) {
+            return v.visitEnumConstant((VariableElement) value, p);
+        } else if (value instanceof Float) {
+            return v.visitFloat((float) value, p);
+        } else if (value instanceof Integer) {
+            return v.visitInt((int) value, p);
+        } else if (value instanceof Long) {
+            return v.visitLong((long) value, p);
+        } else if (value instanceof Short) {
+            return v.visitShort((short) value, p);
+        } else if (value instanceof String) {
+            return v.visitString((String) value, p);
+        } else if (value instanceof TypeMirror) {
+            return v.visitType((TypeMirror) value, p);
+        } else {
+            return v.visitUnknown(this, p);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeCompilationUnit.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class CodeCompilationUnit extends CodeElement<TypeElement> {
+
+    public CodeCompilationUnit() {
+        super(Collections.<Modifier> emptySet());
+    }
+
+    @Override
+    public TypeMirror asType() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ElementKind getKind() {
+        return ElementKind.OTHER;
+    }
+
+    @Override
+    public Name getSimpleName() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        for (Element type : getEnclosedElements()) {
+            if (type.getKind().isClass()) {
+                type.accept(v, p);
+            } else {
+                throw new ClassCastException(type.getClass().getName());
+            }
+        }
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElement.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.java.transform.*;
+
+public abstract class CodeElement<E extends Element> implements Element, GeneratedElement {
+
+    private final Set<Modifier> modifiers;
+    private List<AnnotationMirror> annotations;
+    private List<E> enclosedElements;
+
+    private Element enclosingElement;
+
+    private Element generatorElement;
+    private AnnotationMirror generatorAnnotationMirror;
+
+    public CodeElement() {
+        this.modifiers = new LinkedHashSet<>();
+    }
+
+    public CodeElement(Set<Modifier> modifiers) {
+        this.modifiers = new LinkedHashSet<>(modifiers);
+    }
+
+    @Override
+    public void setGeneratorAnnotationMirror(AnnotationMirror mirror) {
+        this.generatorAnnotationMirror = mirror;
+    }
+
+    @Override
+    public void setGeneratorElement(Element element) {
+        this.generatorElement = element;
+    }
+
+    @Override
+    public AnnotationMirror getGeneratorAnnotationMirror() {
+        return generatorAnnotationMirror;
+    }
+
+    @Override
+    public Element getGeneratorElement() {
+        return generatorElement;
+    }
+
+    public E add(E element) {
+        if (element == null) {
+            throw new NullPointerException();
+        }
+        getEnclosedElements().add(element);
+        return element;
+    }
+
+    public E addOptional(E element) {
+        if (element != null) {
+            add(element);
+        }
+        return element;
+    }
+
+    public void remove(E element) {
+        getEnclosedElements().remove(element);
+    }
+
+    @Override
+    public Set<Modifier> getModifiers() {
+        return modifiers;
+    }
+
+    @Override
+    public List<E> getEnclosedElements() {
+        if (enclosedElements == null) {
+            enclosedElements = parentableList(this, new ArrayList<E>());
+        }
+        return enclosedElements;
+    }
+
+    @Override
+    public List<AnnotationMirror> getAnnotationMirrors() {
+        if (annotations == null) {
+            annotations = parentableList(this, new ArrayList<AnnotationMirror>());
+        }
+        return annotations;
+    }
+
+    /**
+     * Support JDK8 langtools.
+     *
+     * @param annotationType
+     */
+    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Support for some JDK8 builds. (remove after jdk8 is released)
+     *
+     * @param annotationType
+     */
+    public <A extends Annotation> A[] getAnnotations(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Support for some JDK8 builds. (remove after jdk8 is released)
+     *
+     * @param annotationType
+     */
+    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    public void addAnnotationMirror(AnnotationMirror annotationMirror) {
+        getAnnotationMirrors().add(annotationMirror);
+    }
+
+    protected void setEnclosingElement(Element parent) {
+        this.enclosingElement = parent;
+    }
+
+    public Element getEnclosingElement() {
+        return enclosingElement;
+    }
+
+    public CodeTypeElement getEnclosingClass() {
+        Element p = enclosingElement;
+        while (p != null && p.getKind() != ElementKind.CLASS && p.getKind() != ElementKind.ENUM) {
+            p = p.getEnclosingElement();
+        }
+        return (CodeTypeElement) p;
+    }
+
+    <T> List<T> parentableList(Element parent, List<T> list) {
+        return new ParentableList<>(parent, list);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilderCodeWriter codeWriter = new StringBuilderCodeWriter();
+        accept(codeWriter, null);
+        return codeWriter.getString();
+    }
+
+    private static class StringBuilderCodeWriter extends AbstractCodeWriter {
+
+        public StringBuilderCodeWriter() {
+            this.writer = new CharArrayWriter();
+        }
+
+        @Override
+        protected Writer createWriter(CodeTypeElement clazz) throws IOException {
+            return writer;
+        }
+
+        public String getString() {
+            return new String(((CharArrayWriter) writer).toCharArray()).trim();
+        }
+
+    }
+
+    private static class ParentableList<T> implements List<T> {
+
+        private final Element parent;
+        private final List<T> delegate;
+
+        public ParentableList(Element parent, List<T> delegate) {
+            this.parent = parent;
+            this.delegate = delegate;
+        }
+
+        private void addImpl(T element) {
+            if (element != null) {
+                if (element instanceof CodeElement<?>) {
+                    ((CodeElement<?>) element).setEnclosingElement(parent);
+                }
+            }
+        }
+
+        private static void removeImpl(Object element) {
+            if (element instanceof CodeElement<?>) {
+                ((CodeElement<?>) element).setEnclosingElement(null);
+            }
+        }
+
+        @Override
+        public int size() {
+            return delegate.size();
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return delegate.isEmpty();
+        }
+
+        @Override
+        public boolean contains(Object o) {
+            return delegate.contains(o);
+        }
+
+        @Override
+        public Iterator<T> iterator() {
+            return delegate.iterator();
+        }
+
+        @Override
+        public Object[] toArray() {
+            return delegate.toArray();
+        }
+
+        @Override
+        public <E> E[] toArray(E[] a) {
+            return delegate.toArray(a);
+        }
+
+        @Override
+        public boolean add(T e) {
+            addImpl(e);
+            return delegate.add(e);
+        }
+
+        @Override
+        public boolean remove(Object o) {
+            boolean removed = delegate.remove(o);
+            if (removed) {
+                removeImpl(o);
+            }
+            return removed;
+        }
+
+        @Override
+        public boolean containsAll(Collection<?> c) {
+            return delegate.containsAll(c);
+        }
+
+        @Override
+        public boolean addAll(Collection<? extends T> c) {
+            if (c != null) {
+                for (T t : c) {
+                    addImpl(t);
+                }
+            }
+            return delegate.addAll(c);
+        }
+
+        @Override
+        public boolean addAll(int index, Collection<? extends T> c) {
+            if (c != null) {
+                for (T t : c) {
+                    addImpl(t);
+                }
+            }
+            return delegate.addAll(index, c);
+        }
+
+        @Override
+        public boolean removeAll(Collection<?> c) {
+            if (c != null) {
+                for (Object t : c) {
+                    removeImpl(t);
+                }
+            }
+            return delegate.removeAll(c);
+        }
+
+        @Override
+        public String toString() {
+            return delegate.toString();
+        }
+
+        @Override
+        public boolean retainAll(Collection<?> c) {
+            throw new UnsupportedOperationException("Not supported by parentable list");
+        }
+
+        @Override
+        public void clear() {
+            for (Object e : this) {
+                removeImpl(e);
+            }
+            delegate.clear();
+        }
+
+        @Override
+        public T get(int index) {
+            return delegate.get(index);
+        }
+
+        @Override
+        public T set(int index, T element) {
+            removeImpl(delegate.get(index));
+            addImpl(element);
+            return delegate.set(index, element);
+        }
+
+        @Override
+        public void add(int index, T element) {
+            addImpl(element);
+            delegate.add(index, element);
+        }
+
+        @Override
+        public T remove(int index) {
+            T element = delegate.remove(index);
+            removeImpl(element);
+            return element;
+        }
+
+        @Override
+        public int indexOf(Object o) {
+            return delegate.indexOf(o);
+        }
+
+        @Override
+        public int lastIndexOf(Object o) {
+            return delegate.lastIndexOf(o);
+        }
+
+        @Override
+        public ListIterator<T> listIterator() {
+            return delegate.listIterator();
+        }
+
+        @Override
+        public ListIterator<T> listIterator(int index) {
+            return delegate.listIterator(index);
+        }
+
+        @Override
+        public List<T> subList(int fromIndex, int toIndex) {
+            return new ParentableList<>(parent, delegate.subList(fromIndex, toIndex));
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElementScanner.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import javax.lang.model.element.*;
+import javax.lang.model.util.*;
+
+public abstract class CodeElementScanner<R, P> extends ElementScanner7<R, P> {
+
+    @Override
+    public final R visitExecutable(ExecutableElement e, P p) {
+        return visitExecutable(cast(e, CodeExecutableElement.class), p);
+    }
+
+    public R visitExecutable(CodeExecutableElement e, P p) {
+        R ret = super.visitExecutable(e, p);
+        if (e.getBodyTree() != null) {
+            visitTree(e.getBodyTree(), p);
+        }
+        return ret;
+    }
+
+    @Override
+    public R visitPackage(PackageElement e, P p) {
+        return super.visitPackage(e, p);
+    }
+
+    @Override
+    public final R visitType(TypeElement e, P p) {
+        return visitType(cast(e, CodeTypeElement.class), p);
+    }
+
+    public R visitType(CodeTypeElement e, P p) {
+        return super.visitType(e, p);
+    }
+
+    @Override
+    public R visitTypeParameter(TypeParameterElement e, P p) {
+        return super.visitTypeParameter(e, p);
+    }
+
+    private static <E> E cast(Element element, Class<E> clazz) {
+        return clazz.cast(element);
+    }
+
+    public void visitTree(CodeTree e, P p) {
+        for (CodeTree tree : e.getEnclosedElements()) {
+            tree.acceptCodeElementScanner(this, p);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public void visitImport(CodeImport e, P p) {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeExecutableElement.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class CodeExecutableElement extends CodeElement<Element> implements ExecutableElement {
+
+    private final List<TypeMirror> throwables = new ArrayList<>();
+    private final List<VariableElement> parameters = parentableList(this, new ArrayList<VariableElement>());
+
+    private TypeMirror returnType;
+    private Name name;
+
+    private CodeTree bodyTree;
+    private String body;
+    private AnnotationValue defaultValue;
+    private boolean varArgs;
+
+    public CodeExecutableElement(TypeMirror returnType, String name) {
+        super(ElementUtils.modifiers());
+        this.returnType = returnType;
+        this.name = CodeNames.of(name);
+    }
+
+    public CodeExecutableElement(Set<Modifier> modifiers, TypeMirror returnType, String name, CodeVariableElement... parameters) {
+        super(modifiers);
+        this.returnType = returnType;
+        this.name = CodeNames.of(name);
+        for (CodeVariableElement codeParameter : parameters) {
+            addParameter(codeParameter);
+        }
+    }
+
+    /* Support JDK8 langtools. */
+    public boolean isDefault() {
+        return false;
+    }
+
+    @Override
+    public List<TypeMirror> getThrownTypes() {
+        return throwables;
+    }
+
+    @Override
+    public TypeMirror asType() {
+        return returnType;
+    }
+
+    @Override
+    public ElementKind getKind() {
+        if (getReturnType() == null) {
+            return ElementKind.CONSTRUCTOR;
+        } else {
+            return ElementKind.METHOD;
+        }
+    }
+
+    @Override
+    public List<? extends TypeParameterElement> getTypeParameters() {
+        return Collections.emptyList();
+    }
+
+    public void setVarArgs(boolean varargs) {
+        this.varArgs = varargs;
+    }
+
+    @Override
+    public boolean isVarArgs() {
+        return varArgs;
+    }
+
+    public void setDefaultValue(AnnotationValue defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+
+    @Override
+    public AnnotationValue getDefaultValue() {
+        return defaultValue;
+    }
+
+    @Override
+    public Name getSimpleName() {
+        return name;
+    }
+
+    public CodeTreeBuilder getBuilder() {
+        CodeTree tree = this.bodyTree;
+        return createBuilder().tree(tree);
+    }
+
+    public CodeTreeBuilder createBuilder() {
+        CodeTreeBuilder builder = new CodeTreeBuilder(null);
+        this.bodyTree = builder.getTree();
+        this.bodyTree.setEnclosingElement(this);
+        this.body = null;
+        return builder;
+    }
+
+    public void setBodyTree(CodeTree body) {
+        this.bodyTree = body;
+    }
+
+    public CodeTree getBodyTree() {
+        return bodyTree;
+    }
+
+    public TypeMirror getReturnType() {
+        return returnType;
+    }
+
+    @Override
+    public List<VariableElement> getParameters() {
+        return parameters;
+    }
+
+    public TypeMirror[] getParameterTypes() {
+        TypeMirror[] types = new TypeMirror[getParameters().size()];
+        for (int i = 0; i < types.length; i++) {
+            types[i] = parameters.get(i).asType();
+        }
+        return types;
+    }
+
+    public void setReturnType(TypeMirror type) {
+        returnType = type;
+    }
+
+    public void addParameter(VariableElement parameter) {
+        parameters.add(parameter);
+    }
+
+    public void addThrownType(TypeMirror thrownType) {
+        throwables.add(thrownType);
+    }
+
+    public void setSimpleName(Name name) {
+        this.name = name;
+    }
+
+    public void setBody(String body) {
+        this.body = body;
+    }
+
+    public String getBody() {
+        return body;
+    }
+
+    @Override
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        return v.visitExecutable(this, p);
+    }
+
+    public static CodeExecutableElement clone(@SuppressWarnings("unused") ProcessingEnvironment env, ExecutableElement method) {
+        CodeExecutableElement copy = new CodeExecutableElement(method.getReturnType(), method.getSimpleName().toString());
+        for (TypeMirror thrownType : method.getThrownTypes()) {
+            copy.addThrownType(thrownType);
+        }
+        copy.setDefaultValue(method.getDefaultValue());
+
+        for (AnnotationMirror mirror : method.getAnnotationMirrors()) {
+            copy.addAnnotationMirror(mirror);
+        }
+        for (VariableElement var : method.getParameters()) {
+            copy.addParameter(CodeVariableElement.clone(var));
+        }
+        for (Element element : method.getEnclosedElements()) {
+            copy.add(element);
+        }
+        copy.getModifiers().addAll(method.getModifiers());
+        copy.setVarArgs(method.isVarArgs());
+        return copy;
+    }
+
+    public TypeMirror getReceiverType() {
+        throw new UnsupportedOperationException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeImport.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import javax.lang.model.type.*;
+
+public class CodeImport implements Comparable<CodeImport> {
+
+    private final TypeMirror importType;
+    private final String importString;
+    private final boolean staticImport;
+
+    public CodeImport(TypeMirror importedType, String importString, boolean staticImport) {
+        this.importType = importedType;
+        this.importString = importString;
+        this.staticImport = staticImport;
+    }
+
+    public TypeMirror getImportType() {
+        return importType;
+    }
+
+    public boolean isStaticImport() {
+        return staticImport;
+    }
+
+    public String getImportString() {
+        return importString;
+    }
+
+    @Override
+    public int compareTo(CodeImport o) {
+        if (staticImport && !o.staticImport) {
+            return 1;
+        } else if (!staticImport && o.staticImport) {
+            return -1;
+        } else {
+            return importString.compareTo(o.getImportString());
+        }
+    }
+
+    public <P> void accept(CodeElementScanner<?, P> s, P p) {
+        s.visitImport(this, p);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((importString == null) ? 0 : importString.hashCode());
+        result = prime * result + (staticImport ? 1231 : 1237);
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        CodeImport other = (CodeImport) obj;
+        if (importString == null) {
+            if (other.importString != null) {
+                return false;
+            }
+        } else if (!importString.equals(other.importString)) {
+            return false;
+        }
+        if (staticImport != other.staticImport) {
+            return false;
+        }
+        return true;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeNames.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+public abstract class CodeNames {
+
+    private static Map<String, Name> names = new HashMap<>();
+
+    public static Name of(String value) {
+        Name name = names.get(value);
+        if (name == null) {
+            name = new NameImpl(value);
+            names.put(value, name);
+        }
+        return name;
+    }
+
+    private static class NameImpl implements Name {
+
+        private final String name;
+
+        public NameImpl(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public int length() {
+            return name.length();
+        }
+
+        @Override
+        public char charAt(int index) {
+            return name.charAt(index);
+        }
+
+        @Override
+        public CharSequence subSequence(int start, int end) {
+            return name.subSequence(start, end);
+        }
+
+        @Override
+        public boolean contentEquals(CharSequence cs) {
+            return name.contentEquals(cs);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Name) {
+                return ((Name) obj).contentEquals(name);
+            }
+            return super.equals(obj);
+        }
+
+        @Override
+        public int hashCode() {
+            return name.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTree.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class CodeTree extends CodeElement<CodeTree> {
+
+    private final CodeTreeKind kind;
+
+    private TypeMirror type;
+    private final String string;
+
+    CodeTree(CodeTreeKind kind, TypeMirror type, String string) {
+        this.kind = kind;
+        this.type = type;
+        this.string = string;
+    }
+
+    public TypeMirror getType() {
+        return type;
+    }
+
+    public CodeTreeKind getCodeKind() {
+        return kind;
+    }
+
+    public String getString() {
+        return string;
+    }
+
+    public <P> void acceptCodeElementScanner(CodeElementScanner<?, P> s, P p) {
+        s.visitTree(this, p);
+    }
+
+    public void setType(TypeMirror type) {
+        this.type = type;
+    }
+
+    @Override
+    public TypeMirror asType() {
+        return type;
+    }
+
+    @Override
+    public ElementKind getKind() {
+        return ElementKind.OTHER;
+    }
+
+    @Override
+    public Name getSimpleName() {
+        return CodeNames.of(getString());
+    }
+
+    @Override
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        if (v instanceof CodeElementScanner<?, ?>) {
+            acceptCodeElementScanner((CodeElementScanner<?, P>) v, p);
+            return null;
+        } else {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,888 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import static com.oracle.truffle.dsl.processor.java.model.CodeTreeKind.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class CodeTreeBuilder {
+
+    private final CodeTreeBuilder parent;
+
+    private BuilderCodeTree currentElement;
+    private final BuilderCodeTree root;
+
+    private int treeCount;
+
+    public CodeTreeBuilder(CodeTreeBuilder parent) {
+        this.root = new BuilderCodeTree(GROUP, null, null);
+        this.currentElement = root;
+        this.parent = parent;
+    }
+
+    @Override
+    public String toString() {
+        return root.toString();
+    }
+
+    public int getTreeCount() {
+        return treeCount;
+    }
+
+    public boolean isEmpty() {
+        return treeCount == 0;
+    }
+
+    public CodeTreeBuilder statement(String statement) {
+        return startStatement().string(statement).end();
+    }
+
+    public CodeTreeBuilder statement(CodeTree statement) {
+        return startStatement().tree(statement).end();
+    }
+
+    public static CodeTreeBuilder createBuilder() {
+        return new CodeTreeBuilder(null);
+    }
+
+    public static CodeTree singleString(String s) {
+        return new CodeTreeBuilder(null).string(s).getTree();
+    }
+
+    public static CodeTree singleType(TypeMirror s) {
+        return new CodeTreeBuilder(null).type(s).getTree();
+    }
+
+    private CodeTreeBuilder push(CodeTreeKind kind) {
+        return push(new BuilderCodeTree(kind, null, null));
+    }
+
+    private CodeTreeBuilder push(String string) {
+        return push(new BuilderCodeTree(CodeTreeKind.STRING, null, string));
+    }
+
+    private CodeTreeBuilder push(TypeMirror type) {
+        return push(new BuilderCodeTree(CodeTreeKind.TYPE, type, null));
+    }
+
+    private CodeTreeBuilder push(CodeTreeKind kind, TypeMirror type, String string) {
+        return push(new BuilderCodeTree(kind, type, string));
+    }
+
+    private CodeTreeBuilder push(BuilderCodeTree tree) {
+        if (currentElement != null) {
+            if (!removeLastIfEnqueued(tree)) {
+                return this;
+            }
+            currentElement.add(tree);
+        }
+        switch (tree.getCodeKind()) {
+            case COMMA_GROUP:
+            case GROUP:
+            case INDENT:
+                currentElement = tree;
+                break;
+        }
+        treeCount++;
+        return this;
+    }
+
+    private boolean removeLastIfEnqueued(BuilderCodeTree tree) {
+        if (tree.getCodeKind() == REMOVE_LAST) {
+            return !clearLastRec(tree.removeLast, currentElement.getEnclosedElements());
+        }
+        List<CodeTree> childTree = tree.getEnclosedElements();
+        if (!childTree.isEmpty()) {
+            CodeTree last = childTree.get(0);
+            if (last instanceof BuilderCodeTree) {
+                if (!removeLastIfEnqueued((BuilderCodeTree) last)) {
+                    childTree.remove(0);
+                }
+            }
+        }
+        return true;
+    }
+
+    private void clearLast(CodeTreeKind kind) {
+        if (clearLastRec(kind, currentElement.getEnclosedElements())) {
+            treeCount--;
+        } else {
+            // delay clearing the last
+            BuilderCodeTree tree = new BuilderCodeTree(REMOVE_LAST, null, null);
+            tree.removeLast = kind;
+            push(tree);
+        }
+    }
+
+    public CodeTreeBuilder startStatement() {
+        startGroup();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+                string(";").newLine();
+            }
+
+            @Override
+            public void afterEnd() {
+            }
+        });
+        return this;
+    }
+
+    public CodeTreeBuilder startGroup() {
+        return push(CodeTreeKind.GROUP);
+    }
+
+    public CodeTreeBuilder startCommaGroup() {
+        return push(CodeTreeKind.COMMA_GROUP);
+    }
+
+    public CodeTreeBuilder startCall(String callSite) {
+        return startCall((CodeTree) null, callSite);
+    }
+
+    public CodeTreeBuilder startCall(String receiver, String callSite) {
+        return startCall(singleString(receiver), callSite);
+    }
+
+    public CodeTreeBuilder startCall(CodeTree receiver, String callSite) {
+        if (receiver == null) {
+            return startGroup().string(callSite).startParanthesesCommaGroup().endAfter();
+        } else {
+            return startGroup().tree(receiver).string(".").string(callSite).startParanthesesCommaGroup().endAfter();
+        }
+    }
+
+    public CodeTreeBuilder startStaticCall(TypeMirror type, String methodName) {
+        return startGroup().push(CodeTreeKind.STATIC_METHOD_REFERENCE, type, methodName).startParanthesesCommaGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startStaticCall(ExecutableElement method) {
+        return startStaticCall(ElementUtils.findNearestEnclosingType(method).asType(), method.getSimpleName().toString());
+    }
+
+    public CodeTreeBuilder staticReference(TypeMirror type, String fieldName) {
+        return push(CodeTreeKind.STATIC_FIELD_REFERENCE, type, fieldName);
+    }
+
+    private CodeTreeBuilder endAndWhitespaceAfter() {
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string(" ");
+                end();
+            }
+        });
+        return this;
+    }
+
+    private CodeTreeBuilder endAfter() {
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                end();
+            }
+        });
+        return this;
+    }
+
+    private CodeTreeBuilder startParanthesesCommaGroup() {
+        startGroup();
+        string("(").startCommaGroup();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string(")");
+            }
+        });
+        endAfter();
+        return this;
+    }
+
+    private CodeTreeBuilder startCurlyBracesCommaGroup() {
+        startGroup();
+        string("{").startCommaGroup();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string("}");
+            }
+        });
+        endAfter();
+        return this;
+    }
+
+    public CodeTreeBuilder startParantheses() {
+        startGroup();
+        string("(").startGroup();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string(")");
+            }
+        });
+        endAfter();
+        return this;
+    }
+
+    public CodeTreeBuilder doubleQuote(String s) {
+        return startGroup().string("\"" + s + "\"").end();
+    }
+
+    public CodeTreeBuilder string(String chunk1) {
+        return push(chunk1);
+    }
+
+    public CodeTreeBuilder string(String chunk1, String chunk2) {
+        return push(GROUP).string(chunk1).string(chunk2).end();
+    }
+
+    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3) {
+        return push(GROUP).string(chunk1).string(chunk2).string(chunk3).end();
+    }
+
+    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4) {
+        return push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4).end();
+    }
+
+    public CodeTreeBuilder tree(CodeTree treeToAdd) {
+        if (treeToAdd instanceof BuilderCodeTree) {
+            return push((BuilderCodeTree) treeToAdd).end();
+        } else {
+            BuilderCodeTree tree = new BuilderCodeTree(GROUP, null, null);
+            tree.add(treeToAdd);
+            return push(tree).end();
+        }
+    }
+
+    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4, String... chunks) {
+        push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4);
+        for (int i = 0; i < chunks.length; i++) {
+            string(chunks[i]);
+        }
+        return end();
+    }
+
+    public CodeTreeBuilder dot() {
+        return string(".");
+    }
+
+    public CodeTreeBuilder newLine() {
+        return push(NEW_LINE);
+    }
+
+    public CodeTreeBuilder startWhile() {
+        return startGroup().string("while ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startDoBlock() {
+        return startGroup().string("do ").startBlock();
+    }
+
+    public CodeTreeBuilder startDoWhile() {
+        clearLast(CodeTreeKind.NEW_LINE);
+        return startStatement().string(" while ").startParanthesesCommaGroup().endAfter().startGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startIf() {
+        return startGroup().string("if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startFor() {
+        return startGroup().string("for ").startParantheses().endAndWhitespaceAfter().startGroup().endAfter();
+    }
+
+    public boolean startIf(boolean elseIf) {
+        if (elseIf) {
+            startElseIf();
+        } else {
+            startIf();
+        }
+        return true;
+    }
+
+    public CodeTreeBuilder startElseIf() {
+        clearLast(CodeTreeKind.NEW_LINE);
+        return startGroup().string(" else if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startElseBlock() {
+        clearLast(CodeTreeKind.NEW_LINE);
+        return startGroup().string(" else ").startBlock().endAfter();
+    }
+
+    private boolean clearLastRec(CodeTreeKind kind, List<CodeTree> children) {
+        for (int i = children.size() - 1; i >= 0; i--) {
+            CodeTree child = children.get(i);
+            if (child.getCodeKind() == kind) {
+                children.remove(children.get(i));
+                return true;
+            } else {
+                if (clearLastRec(kind, child.getEnclosedElements())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public CodeTreeBuilder startCase() {
+        startGroup().string("case ");
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+                string(" :").newLine();
+            }
+
+            @Override
+            public void afterEnd() {
+            }
+        });
+        return this;
+    }
+
+    public CodeTreeBuilder caseDefault() {
+        return startGroup().string("default :").newLine().end();
+    }
+
+    public CodeTreeBuilder startSwitch() {
+        return startGroup().string("switch ").startParanthesesCommaGroup().endAndWhitespaceAfter();
+    }
+
+    public CodeTreeBuilder startReturn() {
+        ExecutableElement method = findMethod();
+        if (method != null && ElementUtils.isVoid(method.getReturnType())) {
+            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 ");
+        }
+    }
+
+    public CodeTreeBuilder startAssert() {
+        return startStatement().string("assert ");
+    }
+
+    public CodeTreeBuilder startNewArray(ArrayType arrayType, CodeTree size) {
+        startGroup().string("new ").type(arrayType.getComponentType()).string("[");
+        if (size != null) {
+            tree(size);
+        }
+        string("]");
+        if (size == null) {
+            string(" ");
+            startCurlyBracesCommaGroup().endAfter();
+        }
+        return this;
+    }
+
+    public CodeTreeBuilder startNew(TypeMirror uninializedNodeClass) {
+        return startGroup().string("new ").type(uninializedNodeClass).startParanthesesCommaGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startNew(String typeName) {
+        return startGroup().string("new ").string(typeName).startParanthesesCommaGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startIndention() {
+        return push(CodeTreeKind.INDENT);
+    }
+
+    public CodeTreeBuilder end(int times) {
+        for (int i = 0; i < times; i++) {
+            end();
+        }
+        return this;
+    }
+
+    public CodeTreeBuilder end() {
+        BuilderCodeTree tree = currentElement;
+        EndCallback callback = tree.getAtEndListener();
+        if (callback != null) {
+            callback.beforeEnd();
+            toParent();
+            callback.afterEnd();
+        } else {
+            toParent();
+        }
+        return this;
+    }
+
+    private void toParent() {
+        Element parentElement = currentElement.getEnclosingElement();
+        if (currentElement != root) {
+            this.currentElement = (BuilderCodeTree) parentElement;
+        } else {
+            this.currentElement = root;
+        }
+    }
+
+    public CodeTreeBuilder startBlock() {
+        startGroup();
+        string("{").newLine().startIndention();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string("}").newLine();
+            }
+        });
+        endAfter();
+        return this;
+    }
+
+    private void registerCallBack(EndCallback callback) {
+        currentElement.registerAtEnd(callback);
+    }
+
+    public CodeTreeBuilder defaultDeclaration(TypeMirror type, String name) {
+        if (!ElementUtils.isVoid(type)) {
+            startStatement();
+            type(type);
+            string(" ");
+            string(name);
+            string(" = ");
+            defaultValue(type);
+            end(); // statement
+        }
+        return this;
+    }
+
+    public CodeTreeBuilder declaration(TypeMirror type, String name, String init) {
+        return declaration(type, name, singleString(init));
+    }
+
+    public CodeTreeBuilder declaration(String type, String name, CodeTree init) {
+        startStatement();
+        string(type);
+        string(" ");
+        string(name);
+        if (init != null) {
+            string(" = ");
+            tree(init);
+        }
+        end(); // statement
+        return this;
+    }
+
+    public CodeTreeBuilder declaration(String type, String name, String init) {
+        return declaration(type, name, singleString(init));
+    }
+
+    public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTree init) {
+        if (ElementUtils.isVoid(type)) {
+            startStatement();
+            tree(init);
+            end();
+        } else {
+            startStatement();
+            type(type);
+            string(" ");
+            string(name);
+            if (init != null) {
+                string(" = ");
+                tree(init);
+            }
+            end(); // statement
+        }
+        return this;
+    }
+
+    public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTreeBuilder init) {
+        if (init == this) {
+            throw new IllegalArgumentException("Recursive builder usage.");
+        }
+        return declaration(type, name, init.getTree());
+    }
+
+    public CodeTreeBuilder declaration(String type, String name, CodeTreeBuilder init) {
+        if (init == this) {
+            throw new IllegalArgumentException("Recursive builder usage.");
+        }
+        return declaration(type, name, init.getTree());
+    }
+
+    public CodeTreeBuilder declaration(TypeMirror type, String name) {
+        return declaration(type, name, (CodeTree) null);
+    }
+
+    public CodeTreeBuilder create() {
+        return new CodeTreeBuilder(this);
+    }
+
+    public CodeTreeBuilder type(TypeMirror type) {
+        return push(type);
+    }
+
+    public CodeTreeBuilder typeLiteral(TypeMirror type) {
+        return startGroup().type(type).string(".class").end();
+    }
+
+    private void assertRoot() {
+        if (currentElement != root) {
+            throw new IllegalStateException("CodeTreeBuilder was not ended properly.");
+        }
+    }
+
+    public CodeTreeBuilder startCaseBlock() {
+        return startIndention();
+    }
+
+    public CodeTreeBuilder startThrow() {
+        return startStatement().string("throw ");
+    }
+
+    public CodeTree getTree() {
+        assertRoot();
+        return root;
+    }
+
+    public CodeTree getRoot() {
+        return root;
+    }
+
+    public CodeTreeBuilder cast(String baseClassName) {
+        string("(").string(baseClassName).string(") ");
+        return this;
+    }
+
+    public CodeTreeBuilder cast(TypeMirror type, CodeTree content) {
+        if (ElementUtils.isVoid(type)) {
+            tree(content);
+            return this;
+        } else if (type.getKind() == TypeKind.DECLARED && ElementUtils.getQualifiedName(type).equals("java.lang.Object")) {
+            tree(content);
+            return this;
+        } else {
+            return startGroup().string("(").type(type).string(")").string(" ").tree(content).end();
+        }
+    }
+
+    public CodeTreeBuilder startSuperCall() {
+        return string("super").startParanthesesCommaGroup();
+    }
+
+    public CodeTreeBuilder returnFalse() {
+        return startReturn().string("false").end();
+    }
+
+    public CodeTreeBuilder returnStatement() {
+        return statement("return");
+    }
+
+    public ExecutableElement findMethod() {
+        Element element = currentElement;
+        while (element != null && (element.getKind() != ElementKind.METHOD && (element.getKind() != ElementKind.CONSTRUCTOR))) {
+            element = element.getEnclosingElement();
+        }
+        ExecutableElement found = element != null ? (ExecutableElement) element : null;
+        if (found == null && parent != null) {
+            found = parent.findMethod();
+        }
+        return found;
+    }
+
+    public CodeTreeBuilder returnNull() {
+        return startReturn().string("null").end();
+    }
+
+    public CodeTreeBuilder returnTrue() {
+        return startReturn().string("true").end();
+    }
+
+    public CodeTreeBuilder instanceOf(CodeTree var, CodeTree type) {
+        tree(var).string(" instanceof ").tree(type);
+        return this;
+    }
+
+    public CodeTreeBuilder instanceOf(String var, String type) {
+        return instanceOf(singleString(var), singleString(type));
+    }
+
+    public CodeTreeBuilder instanceOf(String var, TypeMirror type) {
+        TypeElement element = ElementUtils.fromTypeMirror(type);
+        if (element == null) {
+            throw new IllegalArgumentException("Cannot call instanceof for a non supported type: " + type.getKind());
+        }
+        return instanceOf(singleString(var), singleType(type));
+    }
+
+    public CodeTreeBuilder defaultValue(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case VOID:
+                return string("");
+            case ARRAY:
+            case DECLARED:
+            case PACKAGE:
+            case NULL:
+                return string("null");
+            case BOOLEAN:
+                return string("false");
+            case BYTE:
+                return string("(byte) 0");
+            case CHAR:
+                return string("(char) 0");
+            case DOUBLE:
+                return string("0.0D");
+            case LONG:
+                return string("0L");
+            case INT:
+                return string("0");
+            case FLOAT:
+                return string("0.0F");
+            case SHORT:
+                return string("(short) 0");
+            default:
+                throw new AssertionError();
+        }
+    }
+
+    public CodeTreeBuilder assertFalse() {
+        return startAssert().string("false").end();
+    }
+
+    public CodeTreeBuilder breakStatement() {
+        return statement("break");
+    }
+
+    public CodeTreeBuilder isNull() {
+        return string(" == null");
+    }
+
+    public CodeTreeBuilder isNotNull() {
+        return string(" != null");
+    }
+
+    public CodeTreeBuilder is(CodeTree tree) {
+        return string(" == ").tree(tree);
+    }
+
+    public CodeTreeBuilder startTryBlock() {
+        return string("try ").startBlock();
+    }
+
+    public CodeTreeBuilder startCatchBlock(TypeMirror exceptionType, String localVarName) {
+        clearLast(CodeTreeKind.NEW_LINE);
+        string(" catch (").type(exceptionType).string(" ").string(localVarName).string(") ");
+        return startBlock();
+    }
+
+    public CodeTreeBuilder startFinallyBlock() {
+        clearLast(CodeTreeKind.NEW_LINE);
+        string(" finally ");
+        return startBlock();
+    }
+
+    public CodeTreeBuilder nullLiteral() {
+        return string("null");
+    }
+
+    private static class BuilderCodeTree extends CodeTree {
+
+        private EndCallback atEndListener;
+        private CodeTreeKind removeLast;
+
+        public BuilderCodeTree(CodeTreeKind kind, TypeMirror type, String string) {
+            super(kind, type, string);
+        }
+
+        public void registerAtEnd(EndCallback atEnd) {
+            if (this.atEndListener != null) {
+                this.atEndListener = new CompoundCallback(this.atEndListener, atEnd);
+            } else {
+                this.atEndListener = atEnd;
+            }
+        }
+
+        public EndCallback getAtEndListener() {
+            return atEndListener;
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder b = new StringBuilder();
+            acceptCodeElementScanner(new Printer(b), null);
+            return b.toString();
+        }
+
+        private static class CompoundCallback implements EndCallback {
+
+            private final EndCallback callback1;
+            private final EndCallback callback2;
+
+            public CompoundCallback(EndCallback callback1, EndCallback callback2) {
+                this.callback1 = callback1;
+                this.callback2 = callback2;
+            }
+
+            @Override
+            public void afterEnd() {
+                callback1.afterEnd();
+                callback2.afterEnd();
+            }
+
+            @Override
+            public void beforeEnd() {
+                callback1.beforeEnd();
+                callback1.beforeEnd();
+            }
+        }
+
+    }
+
+    private interface EndCallback {
+
+        void beforeEnd();
+
+        void afterEnd();
+    }
+
+    private static class Printer extends CodeElementScanner<Void, Void> {
+
+        private int indent;
+        private boolean newLine;
+        private final String ln = "\n";
+
+        private final StringBuilder b;
+
+        Printer(StringBuilder b) {
+            this.b = b;
+        }
+
+        @Override
+        public void visitTree(CodeTree e, Void p) {
+            switch (e.getCodeKind()) {
+                case COMMA_GROUP:
+                    List<CodeTree> children = e.getEnclosedElements();
+                    for (int i = 0; i < children.size(); i++) {
+                        children.get(i).acceptCodeElementScanner(this, p);
+                        if (i < e.getEnclosedElements().size() - 1) {
+                            b.append(", ");
+                        }
+                    }
+                    break;
+                case GROUP:
+                    super.visitTree(e, p);
+                    break;
+                case INDENT:
+                    indent();
+                    super.visitTree(e, p);
+                    dedent();
+                    break;
+                case NEW_LINE:
+                    writeLn();
+                    break;
+                case STRING:
+                    if (e.getString() != null) {
+                        write(e.getString());
+                    } else {
+                        write("null");
+                    }
+                    break;
+                case TYPE:
+                    write(ElementUtils.getSimpleName(e.getType()));
+                    break;
+                default:
+                    assert false;
+                    return;
+            }
+        }
+
+        private void indent() {
+            indent++;
+        }
+
+        private void dedent() {
+            indent--;
+        }
+
+        private void writeLn() {
+            write(ln);
+            newLine = true;
+        }
+
+        private void write(String m) {
+            if (newLine && m != ln) {
+                writeIndent();
+                newLine = false;
+            }
+            b.append(m);
+        }
+
+        private void writeIndent() {
+            for (int i = 0; i < indent; i++) {
+                b.append("    ");
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeKind.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+public enum CodeTreeKind {
+    STATIC_FIELD_REFERENCE,
+    STATIC_METHOD_REFERENCE,
+    GROUP,
+    COMMA_GROUP,
+    REMOVE_LAST,
+    INDENT,
+    STRING,
+    NEW_LINE,
+    TYPE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror;
+
+public class CodeTypeElement extends CodeElement<Element> implements TypeElement {
+
+    private final List<? extends CodeImport> imports = parentableList(this, new ArrayList<CodeImport>());
+
+    private final PackageElement packageElement;
+
+    private final Name simpleName;
+    private final Name packageName;
+    private Name qualifiedName;
+
+    private final List<TypeMirror> implementsInterfaces = new ArrayList<>();
+    private final ElementKind kind;
+    private TypeMirror superClass;
+
+    private final DeclaredCodeTypeMirror mirror = new DeclaredCodeTypeMirror(this);
+
+    public CodeTypeElement(Set<Modifier> modifiers, ElementKind kind, PackageElement packageElement, String simpleName) {
+        super(modifiers);
+        this.kind = kind;
+        this.packageElement = packageElement;
+        this.simpleName = CodeNames.of(simpleName);
+        if (this.packageElement != null) {
+            this.packageName = packageElement.getQualifiedName();
+        } else {
+            this.packageName = CodeNames.of("default");
+        }
+        this.qualifiedName = createQualifiedName();
+    }
+
+    @Override
+    public TypeMirror asType() {
+        return mirror;
+    }
+
+    @Override
+    public ElementKind getKind() {
+        return kind;
+    }
+
+    public boolean containsField(String name) {
+        for (VariableElement field : getFields()) {
+            if (field.getSimpleName().toString().equals(name)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public NestingKind getNestingKind() {
+        return isTopLevelClass() ? NestingKind.TOP_LEVEL : NestingKind.LOCAL;
+    }
+
+    @Override
+    public Element getEnclosingElement() {
+        if (isTopLevelClass()) {
+            return packageElement;
+        } else {
+            return super.getEnclosingElement();
+        }
+    }
+
+    @Override
+    public TypeMirror getSuperclass() {
+        return superClass;
+    }
+
+    @Override
+    public List<TypeMirror> getInterfaces() {
+        return implementsInterfaces;
+    }
+
+    @Override
+    public List<? extends TypeParameterElement> getTypeParameters() {
+        return Collections.emptyList();
+    }
+
+    public boolean isTopLevelClass() {
+        return super.getEnclosingElement() instanceof CodeCompilationUnit;
+    }
+
+    private Name createQualifiedName() {
+        TypeElement enclosingType = getEnclosingClass();
+        if (enclosingType == null) {
+            return CodeNames.of(packageName + "." + simpleName);
+        } else {
+            return CodeNames.of(enclosingType.getQualifiedName() + "." + simpleName);
+        }
+    }
+
+    @Override
+    protected void setEnclosingElement(Element element) {
+        super.setEnclosingElement(element);
+
+        // update qualified name on container change
+        this.qualifiedName = createQualifiedName();
+    }
+
+    public Name getPackageName() {
+        return packageName;
+    }
+
+    @Override
+    public Name getQualifiedName() {
+        return qualifiedName;
+    }
+
+    @Override
+    public Name getSimpleName() {
+        return simpleName;
+    }
+
+    public void setSuperClass(TypeMirror superType) {
+        this.superClass = superType;
+    }
+
+    public List<? extends CodeImport> getImports() {
+        return imports;
+    }
+
+    public List<TypeMirror> getImplements() {
+        return implementsInterfaces;
+    }
+
+    @Override
+    public int hashCode() {
+        return getQualifiedName().hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        } else if (obj instanceof TypeElement) {
+            return getQualifiedName().equals(((TypeElement) obj).getQualifiedName());
+        }
+        return false;
+    }
+
+    public List<VariableElement> getFields() {
+        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());
+    }
+
+    public List<TypeElement> getInnerClasses() {
+        return ElementFilter.typesIn(getEnclosedElements());
+    }
+
+    @Override
+    public String toString() {
+        return getQualifiedName().toString();
+    }
+
+    @Override
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        return v.visitType(this, p);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeMirror.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class CodeTypeMirror implements TypeMirror {
+
+    private final TypeKind kind;
+
+    public CodeTypeMirror(TypeKind kind) {
+        this.kind = kind;
+    }
+
+    @Override
+    public TypeKind getKind() {
+        return kind;
+    }
+
+    @Override
+    public <R, P> R accept(TypeVisitor<R, P> v, P p) {
+        throw new UnsupportedOperationException();
+    }
+
+    public static class ArrayCodeTypeMirror extends CodeTypeMirror implements ArrayType {
+
+        private final TypeMirror component;
+
+        public ArrayCodeTypeMirror(TypeMirror component) {
+            super(TypeKind.ARRAY);
+            this.component = component;
+        }
+
+        @Override
+        public TypeMirror getComponentType() {
+            return component;
+        }
+
+    }
+
+    public static class DeclaredCodeTypeMirror extends CodeTypeMirror implements DeclaredType {
+
+        private final TypeElement clazz;
+        private final List<? extends TypeMirror> typeArguments;
+
+        public DeclaredCodeTypeMirror(TypeElement clazz) {
+            this(clazz, Collections.<TypeMirror> emptyList());
+        }
+
+        public DeclaredCodeTypeMirror(TypeElement clazz, List<? extends TypeMirror> typeArguments) {
+            super(TypeKind.DECLARED);
+            this.clazz = clazz;
+            this.typeArguments = typeArguments;
+        }
+
+        @Override
+        public Element asElement() {
+            return clazz;
+        }
+
+        @Override
+        public TypeMirror getEnclosingType() {
+            return clazz.getEnclosingElement().asType();
+        }
+
+        @Override
+        public List<? extends TypeMirror> getTypeArguments() {
+            return typeArguments;
+        }
+
+        @Override
+        public String toString() {
+            return clazz.getQualifiedName().toString();
+        }
+
+    }
+
+    public List<? extends AnnotationMirror> getAnnotationMirrors() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @param annotationType
+     */
+    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @param annotationType
+     */
+    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeVariableElement.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public final class CodeVariableElement extends CodeElement<Element> implements VariableElement {
+
+    private Name name;
+    private TypeMirror type;
+    private Object constantValue;
+
+    private CodeTree init;
+
+    public CodeVariableElement(TypeMirror type, String name) {
+        super(ElementUtils.modifiers());
+        this.type = type;
+        this.name = CodeNames.of(name);
+    }
+
+    public CodeVariableElement(Set<Modifier> modifiers, TypeMirror type, String name) {
+        super(modifiers);
+        this.type = type;
+        this.name = CodeNames.of(name);
+    }
+
+    public CodeVariableElement(Set<Modifier> modifiers, TypeMirror type, String name, String init) {
+        this(modifiers, type, name);
+        if (init != null) {
+            this.init = new CodeTree(CodeTreeKind.STRING, null, init);
+        }
+    }
+
+    public CodeTreeBuilder createInitBuilder() {
+        CodeTreeBuilder builder = new CodeTreeBuilder(null);
+        init = builder.getTree();
+        init.setEnclosingElement(this);
+        return builder;
+    }
+
+    public void setInit(CodeTree init) {
+        this.init = init;
+    }
+
+    public CodeTree getInit() {
+        return init;
+    }
+
+    public Name getSimpleName() {
+        return name;
+    }
+
+    public TypeMirror getType() {
+        return type;
+    }
+
+    @Override
+    public TypeMirror asType() {
+        return type;
+    }
+
+    @Override
+    public ElementKind getKind() {
+        if (getEnclosingElement() instanceof ExecutableElement) {
+            return ElementKind.PARAMETER;
+        } else if (getEnclosingElement() instanceof TypeElement) {
+            return ElementKind.FIELD;
+        } else {
+            return ElementKind.PARAMETER;
+        }
+    }
+
+    public void setConstantValue(Object constantValue) {
+        this.constantValue = constantValue;
+    }
+
+    @Override
+    public Object getConstantValue() {
+        return constantValue;
+    }
+
+    public String getName() {
+        return getSimpleName().toString();
+    }
+
+    public void setSimpleName(Name name) {
+        this.name = name;
+    }
+
+    public void setName(String name) {
+        this.name = CodeNames.of(name);
+    }
+
+    public void setType(TypeMirror type) {
+        this.type = type;
+    }
+
+    @Override
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        return v.visitVariable(this, p);
+    }
+
+    public static CodeVariableElement clone(VariableElement var) {
+        CodeVariableElement copy = new CodeVariableElement(var.getModifiers(), var.asType(), var.getSimpleName().toString());
+        copy.setConstantValue(var.getConstantValue());
+        for (AnnotationMirror mirror : var.getAnnotationMirrors()) {
+            copy.addAnnotationMirror(mirror);
+        }
+        for (Element element : var.getEnclosedElements()) {
+            copy.add(element);
+        }
+        return copy;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedElement.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import javax.lang.model.element.*;
+
+public interface GeneratedElement {
+
+    AnnotationMirror getGeneratorAnnotationMirror();
+
+    void setGeneratorAnnotationMirror(AnnotationMirror mirror);
+
+    Element getGeneratorElement();
+
+    void setGeneratorElement(Element element);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedPackageElement.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public final class GeneratedPackageElement extends CodeElement<Element> implements PackageElement {
+
+    private final Name qualifiedName;
+    private final Name simpleName;
+
+    public GeneratedPackageElement(String qualifiedName) {
+        this.qualifiedName = CodeNames.of(qualifiedName);
+        int lastIndex = qualifiedName.lastIndexOf('.');
+        if (lastIndex == -1) {
+            simpleName = CodeNames.of("");
+        } else {
+            simpleName = CodeNames.of(qualifiedName.substring(lastIndex, qualifiedName.length()));
+        }
+    }
+
+    public TypeMirror asType() {
+        throw new UnsupportedOperationException();
+    }
+
+    public ElementKind getKind() {
+        return ElementKind.PACKAGE;
+    }
+
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        return v.visitPackage(this, p);
+    }
+
+    public Name getQualifiedName() {
+        return qualifiedName;
+    }
+
+    public Name getSimpleName() {
+        return simpleName;
+    }
+
+    public boolean isUnnamed() {
+        return simpleName.toString().equals("");
+    }
+
+    @Override
+    public int hashCode() {
+        return qualifiedName.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof PackageElement) {
+            return qualifiedName.equals(((PackageElement) obj).getQualifiedName());
+        }
+        return super.equals(obj);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeElement.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+public final class GeneratedTypeElement extends CodeTypeElement {
+
+    public GeneratedTypeElement(Set<Modifier> modifiers, ElementKind kind, PackageElement packageElement, String simpleName) {
+        super(modifiers, kind, packageElement, simpleName);
+        setEnclosingElement(packageElement);
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeMirror.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror;
+
+public final class GeneratedTypeMirror extends DeclaredCodeTypeMirror {
+
+    public GeneratedTypeMirror(String packageName, String name) {
+        super(new GeneratedTypeElement(Collections.<Modifier> emptySet(), ElementKind.CLASS, new GeneratedPackageElement(packageName), name));
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/AbstractCodeWriter.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,758 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.transform;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import java.io.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public abstract class AbstractCodeWriter extends CodeElementScanner<Void, Void> {
+
+    private static final int MAX_LINE_LENGTH = 200;
+    private static final int LINE_WRAP_INDENTS = 3;
+    private static final String IDENT_STRING = "    ";
+    private static final String LN = "\n"; /* unix style */
+
+    protected Writer writer;
+    private int indent;
+    private boolean newLine;
+    private int lineLength;
+    private boolean lineWrapping = false;
+
+    private OrganizedImports imports;
+
+    protected abstract Writer createWriter(CodeTypeElement clazz) throws IOException;
+
+    @Override
+    public Void visitType(CodeTypeElement e, Void p) {
+        if (e.isTopLevelClass()) {
+            Writer w = null;
+            try {
+                imports = OrganizedImports.organize(e);
+                w = new TrimTrailingSpaceWriter(createWriter(e));
+                writer = w;
+                writeRootClass(e);
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            } finally {
+                if (w != null) {
+                    try {
+                        w.close();
+                    } catch (Throwable e1) {
+                        // see eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=361378
+                        // TODO temporary suppress errors on close.
+                    }
+                }
+                writer = null;
+            }
+        } else {
+            writeClassImpl(e);
+        }
+        return null;
+    }
+
+    private void writeRootClass(CodeTypeElement e) {
+        writeHeader();
+        write("package ").write(e.getPackageName()).write(";").writeLn();
+        writeEmptyLn();
+
+        Set<CodeImport> generateImports = imports.generateImports();
+        List<CodeImport> typeImports = new ArrayList<>();
+        List<CodeImport> staticImports = new ArrayList<>();
+
+        for (CodeImport codeImport : generateImports) {
+            if (codeImport.isStaticImport()) {
+                staticImports.add(codeImport);
+            } else {
+                typeImports.add(codeImport);
+            }
+        }
+        Collections.sort(typeImports);
+        Collections.sort(staticImports);
+
+        for (CodeImport imp : staticImports) {
+            imp.accept(this, null);
+            writeLn();
+        }
+        if (!staticImports.isEmpty()) {
+            writeEmptyLn();
+        }
+
+        for (CodeImport imp : typeImports) {
+            imp.accept(this, null);
+            writeLn();
+        }
+        if (!typeImports.isEmpty()) {
+            writeEmptyLn();
+        }
+
+        writeClassImpl(e);
+    }
+
+    private String useImport(Element enclosedType, TypeMirror type) {
+        if (imports != null) {
+            return imports.createTypeReference(enclosedType, type);
+        } else {
+            return ElementUtils.getSimpleName(type);
+        }
+    }
+
+    private void writeClassImpl(CodeTypeElement e) {
+        for (AnnotationMirror annotation : e.getAnnotationMirrors()) {
+            visitAnnotation(e, annotation);
+            writeLn();
+        }
+
+        writeModifiers(e.getModifiers());
+        if (e.getKind() == ElementKind.ENUM) {
+            write("enum ");
+        } else {
+            write("class ");
+        }
+        write(e.getSimpleName());
+        if (e.getSuperclass() != null && !getQualifiedName(e.getSuperclass()).equals("java.lang.Object")) {
+            write(" extends ").write(useImport(e, e.getSuperclass()));
+        }
+        if (e.getImplements().size() > 0) {
+            write(" implements ");
+            for (int i = 0; i < e.getImplements().size(); i++) {
+                write(useImport(e, e.getImplements().get(i)));
+                if (i < e.getImplements().size() - 1) {
+                    write(", ");
+                }
+            }
+        }
+
+        write(" {").writeLn();
+        writeEmptyLn();
+        indent(1);
+
+        List<VariableElement> staticFields = getStaticFields(e);
+        List<VariableElement> instanceFields = getInstanceFields(e);
+
+        for (int i = 0; i < staticFields.size(); i++) {
+            VariableElement field = staticFields.get(i);
+            field.accept(this, null);
+            if (e.getKind() == ElementKind.ENUM && i < staticFields.size() - 1) {
+                write(",");
+                writeLn();
+            } else {
+                write(";");
+                writeLn();
+            }
+        }
+
+        if (staticFields.size() > 0) {
+            writeEmptyLn();
+        }
+
+        for (VariableElement field : instanceFields) {
+            field.accept(this, null);
+            write(";");
+            writeLn();
+        }
+        if (instanceFields.size() > 0) {
+            writeEmptyLn();
+        }
+
+        for (ExecutableElement method : ElementFilter.constructorsIn(e.getEnclosedElements())) {
+            method.accept(this, null);
+        }
+
+        for (ExecutableElement method : getInstanceMethods(e)) {
+            method.accept(this, null);
+        }
+
+        for (ExecutableElement method : getStaticMethods(e)) {
+            method.accept(this, null);
+        }
+
+        for (TypeElement clazz : e.getInnerClasses()) {
+            clazz.accept(this, null);
+        }
+
+        dedent(1);
+        write("}");
+        writeEmptyLn();
+    }
+
+    private static List<VariableElement> getStaticFields(CodeTypeElement clazz) {
+        List<VariableElement> staticFields = new ArrayList<>();
+        for (VariableElement field : clazz.getFields()) {
+            if (field.getModifiers().contains(Modifier.STATIC)) {
+                staticFields.add(field);
+            }
+        }
+        return staticFields;
+    }
+
+    private static List<VariableElement> getInstanceFields(CodeTypeElement clazz) {
+        List<VariableElement> instanceFields = new ArrayList<>();
+        for (VariableElement field : clazz.getFields()) {
+            if (!field.getModifiers().contains(Modifier.STATIC)) {
+                instanceFields.add(field);
+            }
+        }
+        return instanceFields;
+    }
+
+    private static List<ExecutableElement> getStaticMethods(CodeTypeElement clazz) {
+        List<ExecutableElement> staticMethods = new ArrayList<>();
+        for (ExecutableElement method : clazz.getMethods()) {
+            if (method.getModifiers().contains(Modifier.STATIC)) {
+                staticMethods.add(method);
+            }
+        }
+        return staticMethods;
+    }
+
+    private static List<ExecutableElement> getInstanceMethods(CodeTypeElement clazz) {
+        List<ExecutableElement> instanceMethods = new ArrayList<>();
+        for (ExecutableElement method : clazz.getMethods()) {
+            if (!method.getModifiers().contains(Modifier.STATIC)) {
+                instanceMethods.add(method);
+            }
+        }
+        return instanceMethods;
+    }
+
+    @Override
+    public Void visitVariable(VariableElement f, Void p) {
+        Element parent = f.getEnclosingElement();
+
+        for (AnnotationMirror annotation : f.getAnnotationMirrors()) {
+            visitAnnotation(f, annotation);
+            write(" ");
+        }
+
+        CodeTree init = null;
+        if (f instanceof CodeVariableElement) {
+            init = ((CodeVariableElement) f).getInit();
+        }
+
+        if (parent.getKind() == ElementKind.ENUM && f.getModifiers().contains(Modifier.STATIC)) {
+            write(f.getSimpleName());
+            if (init != null) {
+                write("(");
+                init.acceptCodeElementScanner(this, p);
+                write(")");
+            }
+        } else {
+            Element enclosing = f.getEnclosingElement();
+            writeModifiers(f.getModifiers());
+
+            boolean varArgs = false;
+            if (enclosing.getKind() == ElementKind.METHOD) {
+                ExecutableElement method = (ExecutableElement) enclosing;
+                if (method.isVarArgs() && method.getParameters().indexOf(f) == method.getParameters().size() - 1) {
+                    varArgs = true;
+                }
+            }
+
+            TypeMirror varType = f.asType();
+            if (varArgs) {
+                if (varType.getKind() == TypeKind.ARRAY) {
+                    varType = ((ArrayType) varType).getComponentType();
+                }
+                write(useImport(f, varType));
+                write("...");
+            } else {
+                write(useImport(f, varType));
+            }
+
+            write(" ");
+            write(f.getSimpleName());
+            if (init != null) {
+                write(" = ");
+                init.acceptCodeElementScanner(this, p);
+            }
+        }
+        return null;
+    }
+
+    private void visitAnnotation(Element enclosedElement, AnnotationMirror e) {
+        write("@").write(useImport(enclosedElement, e.getAnnotationType()));
+
+        if (!e.getElementValues().isEmpty()) {
+            write("(");
+            final ExecutableElement defaultElement = findExecutableElement(e.getAnnotationType(), "value");
+
+            Map<? extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues();
+            if (defaultElement != null && values.size() == 1 && values.get(defaultElement) != null) {
+                visitAnnotationValue(enclosedElement, values.get(defaultElement));
+            } else {
+                Set<? extends ExecutableElement> methodsSet = values.keySet();
+                List<ExecutableElement> methodsList = new ArrayList<>();
+                for (ExecutableElement method : methodsSet) {
+                    if (values.get(method) == null) {
+                        continue;
+                    }
+                    methodsList.add(method);
+                }
+
+                Collections.sort(methodsList, new Comparator<ExecutableElement>() {
+
+                    @Override
+                    public int compare(ExecutableElement o1, ExecutableElement o2) {
+                        return o1.getSimpleName().toString().compareTo(o2.getSimpleName().toString());
+                    }
+                });
+
+                for (int i = 0; i < methodsList.size(); i++) {
+                    ExecutableElement method = methodsList.get(i);
+                    AnnotationValue value = values.get(method);
+                    write(method.getSimpleName().toString());
+                    write(" = ");
+                    visitAnnotationValue(enclosedElement, value);
+
+                    if (i < methodsList.size() - 1) {
+                        write(", ");
+                    }
+                }
+            }
+
+            write(")");
+        }
+    }
+
+    private void visitAnnotationValue(Element enclosedElement, AnnotationValue e) {
+        e.accept(new AnnotationValueWriterVisitor(enclosedElement), null);
+    }
+
+    private class AnnotationValueWriterVisitor extends AbstractAnnotationValueVisitor7<Void, Void> {
+
+        private final Element enclosedElement;
+
+        public AnnotationValueWriterVisitor(Element enclosedElement) {
+            this.enclosedElement = enclosedElement;
+        }
+
+        @Override
+        public Void visitBoolean(boolean b, Void p) {
+            write(Boolean.toString(b));
+            return null;
+        }
+
+        @Override
+        public Void visitByte(byte b, Void p) {
+            write(Byte.toString(b));
+            return null;
+        }
+
+        @Override
+        public Void visitChar(char c, Void p) {
+            write(Character.toString(c));
+            return null;
+        }
+
+        @Override
+        public Void visitDouble(double d, Void p) {
+            write(Double.toString(d));
+            return null;
+        }
+
+        @Override
+        public Void visitFloat(float f, Void p) {
+            write(Float.toString(f));
+            return null;
+        }
+
+        @Override
+        public Void visitInt(int i, Void p) {
+            write(Integer.toString(i));
+            return null;
+        }
+
+        @Override
+        public Void visitLong(long i, Void p) {
+            write(Long.toString(i));
+            return null;
+        }
+
+        @Override
+        public Void visitShort(short s, Void p) {
+            write(Short.toString(s));
+            return null;
+        }
+
+        @Override
+        public Void visitString(String s, Void p) {
+            write("\"");
+            write(s);
+            write("\"");
+            return null;
+        }
+
+        @Override
+        public Void visitType(TypeMirror t, Void p) {
+            write(useImport(enclosedElement, t));
+            write(".class");
+            return null;
+        }
+
+        @Override
+        public Void visitEnumConstant(VariableElement c, Void p) {
+            write(useImport(enclosedElement, c.asType()));
+            write(".");
+            write(c.getSimpleName().toString());
+            return null;
+        }
+
+        @Override
+        public Void visitAnnotation(AnnotationMirror a, Void p) {
+            AbstractCodeWriter.this.visitAnnotation(enclosedElement, a);
+            return null;
+        }
+
+        @Override
+        public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
+            write("{");
+            for (int i = 0; i < vals.size(); i++) {
+                AnnotationValue value = vals.get(i);
+                AbstractCodeWriter.this.visitAnnotationValue(enclosedElement, value);
+                if (i < vals.size() - 1) {
+                    write(", ");
+                }
+            }
+            write("}");
+            return null;
+        }
+    }
+
+    private static ExecutableElement findExecutableElement(DeclaredType type, String name) {
+        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements());
+        for (ExecutableElement executableElement : elements) {
+            if (executableElement.getSimpleName().toString().equals(name)) {
+                return executableElement;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public void visitImport(CodeImport e, Void p) {
+        if (e.isStaticImport()) {
+            write("import static ").write(e.getImportString()).write(";");
+        } else {
+            write("import ").write(e.getImportString()).write(";");
+        }
+    }
+
+    @Override
+    public Void visitExecutable(CodeExecutableElement e, Void p) {
+        for (AnnotationMirror annotation : e.getAnnotationMirrors()) {
+            visitAnnotation(e, annotation);
+            writeLn();
+        }
+
+        writeModifiers(e.getModifiers());
+
+        if (e.getReturnType() != null) {
+            write(useImport(e, e.getReturnType()));
+            write(" ");
+        }
+        write(e.getSimpleName());
+        write("(");
+
+        for (int i = 0; i < e.getParameters().size(); i++) {
+            VariableElement param = e.getParameters().get(i);
+            param.accept(this, p);
+            if (i < e.getParameters().size() - 1) {
+                write(", ");
+            }
+        }
+        write(")");
+
+        List<TypeMirror> throwables = e.getThrownTypes();
+        if (throwables.size() > 0) {
+            write(" throws ");
+            for (int i = 0; i < throwables.size(); i++) {
+                write(useImport(e, throwables.get(i)));
+                if (i < throwables.size() - 1) {
+                    write(", ");
+                }
+            }
+        }
+
+        if (e.getModifiers().contains(Modifier.ABSTRACT)) {
+            writeLn(";");
+        } else if (e.getBodyTree() != null) {
+            writeLn(" {");
+            indent(1);
+            e.getBodyTree().acceptCodeElementScanner(this, p);
+            dedent(1);
+            writeLn("}");
+        } else if (e.getBody() != null) {
+            write(" {");
+            write(e.getBody());
+            writeLn("}");
+        } else {
+            writeLn("{ }");
+        }
+        writeEmptyLn();
+        return null;
+    }
+
+    @Override
+    public void visitTree(CodeTree e, Void p) {
+        CodeTreeKind kind = e.getCodeKind();
+
+        switch (kind) {
+            case COMMA_GROUP:
+                List<CodeTree> children = e.getEnclosedElements();
+                for (int i = 0; i < children.size(); i++) {
+                    children.get(i).acceptCodeElementScanner(this, p);
+                    if (i < e.getEnclosedElements().size() - 1) {
+                        write(", ");
+                    }
+                }
+                break;
+            case GROUP:
+                for (CodeTree tree : e.getEnclosedElements()) {
+                    tree.acceptCodeElementScanner(this, p);
+                }
+                break;
+            case INDENT:
+                indent(1);
+                for (CodeTree tree : e.getEnclosedElements()) {
+                    tree.acceptCodeElementScanner(this, p);
+                }
+                dedent(1);
+                break;
+            case NEW_LINE:
+                writeLn();
+                break;
+            case STRING:
+                if (e.getString() != null) {
+                    write(e.getString());
+                } else {
+                    write("null");
+                }
+                break;
+            case STATIC_FIELD_REFERENCE:
+                if (e.getString() != null) {
+                    write(imports.createStaticFieldReference(e, e.getType(), e.getString()));
+                } else {
+                    write("null");
+                }
+                break;
+            case STATIC_METHOD_REFERENCE:
+                if (e.getString() != null) {
+                    write(imports.createStaticMethodReference(e, e.getType(), e.getString()));
+                } else {
+                    write("null");
+                }
+                break;
+            case TYPE:
+                write(useImport(e, e.getType()));
+                break;
+            default:
+                assert false;
+                return;
+        }
+    }
+
+    protected void writeHeader() {
+        // default implementation does nothing
+    }
+
+    private void writeModifiers(Set<Modifier> modifiers) {
+        if (modifiers != null) {
+            for (Modifier modifier : modifiers) {
+                write(modifier.toString());
+                write(" ");
+            }
+        }
+    }
+
+    private void indent(int count) {
+        indent += count;
+    }
+
+    private void dedent(int count) {
+        indent -= count;
+    }
+
+    private void writeLn() {
+        writeLn("");
+    }
+
+    protected void writeLn(String text) {
+        write(text);
+        write(LN);
+        lineLength = 0;
+        newLine = true;
+        if (lineWrapping) {
+            dedent(LINE_WRAP_INDENTS);
+            lineWrapping = false;
+        }
+        lineWrapping = false;
+    }
+
+    private void writeEmptyLn() {
+        writeLn();
+    }
+
+    private AbstractCodeWriter write(Name name) {
+        return write(name.toString());
+    }
+
+    private AbstractCodeWriter write(String m) {
+        if (m.isEmpty()) {
+            return this;
+        }
+        try {
+            String s = m;
+            lineLength += s.length();
+            if (newLine && s != LN) {
+                writeIndent();
+                newLine = false;
+            }
+            if (lineLength > MAX_LINE_LENGTH) {
+                s = wrapLine(s);
+            }
+            writer.write(s);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        return this;
+    }
+
+    private String wrapLine(String m) throws IOException {
+        assert !m.isEmpty();
+
+        char firstCharacter = m.charAt(0);
+        char lastCharacter = m.charAt(m.length() - 1);
+        if (firstCharacter == '\"' && lastCharacter == '\"') {
+            // string line wrapping
+            String string = m.substring(1, m.length() - 1);
+            if (string.isEmpty()) {
+                return m;
+            }
+
+            // restore original line length
+            lineLength = lineLength - m.length();
+            int size = 0;
+            for (int i = 0; i < string.length(); i += size) {
+                if (i != 0) {
+                    write("+ ");
+                }
+
+                int nextSize = MAX_LINE_LENGTH - lineLength - 2;
+                if (nextSize <= 0) {
+                    writeLn();
+                    nextSize = MAX_LINE_LENGTH - lineLength - 2;
+                }
+
+                int end = Math.min(i + nextSize, string.length());
+
+                // TODO(CH): fails in normal usage - output ok though
+                // assert lineLength + (end - i) + 2 < MAX_LINE_LENGTH;
+
+                write("\"" + string.substring(i, end) + "\"");
+                size = nextSize;
+            }
+
+            return "";
+        } else if (!Character.isAlphabetic(firstCharacter) && firstCharacter != '+') {
+            return m;
+        }
+
+        if (!lineWrapping) {
+            indent(LINE_WRAP_INDENTS);
+        }
+        lineWrapping = true;
+        lineLength = 0;
+        write(LN);
+        writeIndent();
+        return m;
+    }
+
+    private void writeIndent() throws IOException {
+        lineLength += indentSize();
+        for (int i = 0; i < indent; i++) {
+            writer.write(IDENT_STRING);
+        }
+    }
+
+    private int indentSize() {
+        return IDENT_STRING.length() * indent;
+    }
+
+    private static class TrimTrailingSpaceWriter extends Writer {
+
+        private final Writer delegate;
+        private final StringBuilder buffer = new StringBuilder();
+
+        public TrimTrailingSpaceWriter(Writer delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public void close() throws IOException {
+            this.delegate.close();
+        }
+
+        @Override
+        public void flush() throws IOException {
+            this.delegate.flush();
+        }
+
+        @Override
+        public void write(char[] cbuf, int off, int len) throws IOException {
+            buffer.append(cbuf, off, len);
+            int newLinePoint = buffer.indexOf(LN);
+
+            if (newLinePoint != -1) {
+                String lhs = trimTrailing(buffer.substring(0, newLinePoint));
+                delegate.write(lhs);
+                delegate.write(LN);
+                buffer.delete(0, newLinePoint + 1);
+            }
+        }
+
+        private static String trimTrailing(String s) {
+            int cut = 0;
+            for (int i = s.length() - 1; i >= 0; i--) {
+                if (Character.isWhitespace(s.charAt(i))) {
+                    cut++;
+                } else {
+                    break;
+                }
+            }
+            if (cut > 0) {
+                return s.substring(0, s.length() - cut);
+            }
+            return s;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/FixWarningsVisitor.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.transform;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.io.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public class FixWarningsVisitor extends CodeElementScanner<Void, Void> {
+
+    private final Set<String> symbolsUsed = new HashSet<>();
+
+    private final ProcessorContext context;
+    private final DeclaredType unusedAnnotation;
+    private final DeclaredType overrideType;
+
+    public FixWarningsVisitor(ProcessorContext context, DeclaredType unusedAnnotation, DeclaredType overrideType) {
+        this.context = context;
+        this.unusedAnnotation = unusedAnnotation;
+        this.overrideType = overrideType;
+    }
+
+    @Override
+    public Void visitType(CodeTypeElement e, Void p) {
+        List<TypeElement> superTypes = ElementUtils.getSuperTypes(e);
+        for (TypeElement type : superTypes) {
+            String qualifiedName = ElementUtils.getQualifiedName(type);
+            if (qualifiedName.equals(Serializable.class.getCanonicalName())) {
+                if (!e.containsField("serialVersionUID")) {
+                    e.add(new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), context.getType(long.class), "serialVersionUID", "1L"));
+                }
+                break;
+            }
+        }
+
+        return super.visitType(e, p);
+    }
+
+    @Override
+    public Void visitExecutable(CodeExecutableElement e, Void p) {
+        if (e.getParameters().isEmpty()) {
+            return null;
+        } else if (e.getModifiers().contains(Modifier.ABSTRACT)) {
+            return null;
+        } else if (containsOverride(e)) {
+            return null;
+        }
+
+        symbolsUsed.clear();
+        super.visitExecutable(e, p);
+
+        for (VariableElement parameter : e.getParameters()) {
+            if (!symbolsUsed.contains(parameter.getSimpleName().toString())) {
+                e.getAnnotationMirrors().add(createUnusedAnnotationMirror());
+                break;
+            }
+        }
+        return null;
+    }
+
+    private boolean containsOverride(CodeExecutableElement e) {
+        for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
+            if (ElementUtils.typeEquals(overrideType, mirror.getAnnotationType())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private CodeAnnotationMirror createUnusedAnnotationMirror() {
+        CodeAnnotationMirror mirror = new CodeAnnotationMirror(unusedAnnotation);
+        mirror.setElementValue(mirror.findExecutableElement("value"), new CodeAnnotationValue("unused"));
+        return mirror;
+    }
+
+    @Override
+    public void visitTree(CodeTree e, Void p) {
+        if (e.getString() != null) {
+            computeSymbols(e.getString());
+        }
+        super.visitTree(e, p);
+    }
+
+    private void computeSymbols(String s) {
+        // TODO there should not be any need for a StringTokenizer if we have a real AST for
+        // method bodies. Also the current solution is not perfect. What if one token
+        // is spread across multiple CodeTree instances? But for now that works.
+        StringTokenizer tokenizer = new StringTokenizer(s, ".= :,()[];{}\"\"'' ", false);
+        while (tokenizer.hasMoreElements()) {
+            String token = tokenizer.nextToken().trim();
+            if (token.length() > 0) {
+                symbolsUsed.add(token);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/GenerateOverrideVisitor.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.transform;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public class GenerateOverrideVisitor extends CodeElementScanner<Void, Void> {
+
+    private final DeclaredType overrideType;
+
+    public GenerateOverrideVisitor(DeclaredType overrideType) {
+        this.overrideType = overrideType;
+    }
+
+    @Override
+    public Void visitExecutable(CodeExecutableElement e, Void p) {
+        if (!e.getModifiers().contains(Modifier.STATIC) && !e.getModifiers().contains(Modifier.PRIVATE)) {
+            String name = e.getSimpleName().toString();
+            TypeMirror[] params = e.getParameterTypes();
+
+            for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
+                if (ElementUtils.typeEquals(overrideType, mirror.getAnnotationType())) {
+                    // already declared (may happen if method copied from super class)
+                    return super.visitExecutable(e, p);
+                }
+            }
+
+            if (isDeclaredMethodInSuperType(e.getEnclosingClass(), name, params)) {
+                e.addAnnotationMirror(new CodeAnnotationMirror(overrideType));
+            }
+        }
+        return super.visitExecutable(e, p);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/OrganizedImports.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.transform;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public final class OrganizedImports {
+
+    private final Set<TypeMirror> staticImportUsage = new HashSet<>();
+
+    private final Map<String, TypeMirror> simpleNamesUsed = new HashMap<>();
+
+    private final Set<String> declaredStaticMethods = new HashSet<>();
+    private final Set<String> declaredStaticFields = new HashSet<>();
+    private final Set<String> ambiguousStaticMethods = new HashSet<>();
+    private final Set<String> ambiguousStaticFields = new HashSet<>();
+
+    private final CodeTypeElement topLevelClass;
+
+    private OrganizedImports(CodeTypeElement topLevelClass) {
+        this.topLevelClass = topLevelClass;
+    }
+
+    public static OrganizedImports organize(CodeTypeElement topLevelClass) {
+        OrganizedImports organized = new OrganizedImports(topLevelClass);
+        organized.organizeImpl();
+        return organized;
+    }
+
+    private void organizeImpl() {
+        ImportTypeReferenceVisitor reference = new ImportTypeReferenceVisitor();
+        topLevelClass.accept(reference, null);
+
+        processStaticImports(topLevelClass);
+        List<TypeElement> types = ElementUtils.getSuperTypes(topLevelClass);
+        for (TypeElement typeElement : types) {
+            processStaticImports(typeElement);
+        }
+
+        for (TypeMirror type : staticImportUsage) {
+            TypeElement element = fromTypeMirror(type);
+            if (element != null) {
+                // already processed by supertype
+                if (types.contains(element)) {
+                    continue;
+                }
+                processStaticImports(element);
+            }
+        }
+    }
+
+    public String createTypeReference(Element enclosedElement, TypeMirror type) {
+        switch (type.getKind()) {
+            case BOOLEAN:
+            case BYTE:
+            case CHAR:
+            case DOUBLE:
+            case FLOAT:
+            case SHORT:
+            case INT:
+            case LONG:
+            case VOID:
+                return ElementUtils.getSimpleName(type);
+            case DECLARED:
+                return createDeclaredTypeName(enclosedElement, (DeclaredType) type);
+            case ARRAY:
+                return createTypeReference(enclosedElement, ((ArrayType) type).getComponentType()) + "[]";
+            case WILDCARD:
+                return createWildcardName(enclosedElement, (WildcardType) type);
+            case TYPEVAR:
+                return "?";
+            default:
+                throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type);
+        }
+    }
+
+    public String createStaticFieldReference(Element enclosedElement, TypeMirror type, String fieldName) {
+        return createStaticReference(enclosedElement, type, fieldName, ambiguousStaticFields);
+    }
+
+    public String createStaticMethodReference(Element enclosedElement, TypeMirror type, String methodName) {
+        return createStaticReference(enclosedElement, type, methodName, ambiguousStaticMethods);
+    }
+
+    private String createStaticReference(Element enclosedElement, TypeMirror type, String name, Set<String> ambiguousSymbols) {
+        if (ambiguousSymbols.contains(name)) {
+            // ambiguous import
+            return createTypeReference(enclosedElement, type) + "." + name;
+        } else {
+            // import declared and not ambiguous
+            return name;
+        }
+    }
+
+    private String createWildcardName(Element enclosedElement, WildcardType type) {
+        StringBuilder b = new StringBuilder();
+        if (type.getExtendsBound() != null) {
+            b.append("? extends ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
+        } else if (type.getSuperBound() != null) {
+            b.append("? super ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
+        }
+        return b.toString();
+    }
+
+    private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) {
+        String name;
+        name = ElementUtils.fixECJBinaryNameIssue(type.asElement().getSimpleName().toString());
+
+        if (needsImport(enclosedElement, type)) {
+            TypeMirror usedByType = simpleNamesUsed.get(name);
+            if (usedByType == null) {
+                simpleNamesUsed.put(name, type);
+                usedByType = type;
+            }
+
+            if (!typeEquals(type, usedByType)) {
+                name = getQualifiedName(type);
+            }
+        }
+
+        if (type.getTypeArguments().size() == 0) {
+            return name;
+        }
+
+        StringBuilder b = new StringBuilder(name);
+        b.append("<");
+        if (type.getTypeArguments().size() > 0) {
+            for (int i = 0; i < type.getTypeArguments().size(); i++) {
+                b.append(createTypeReference(enclosedElement, type.getTypeArguments().get(i)));
+                if (i < type.getTypeArguments().size() - 1) {
+                    b.append(", ");
+                }
+            }
+        }
+        b.append(">");
+        return b.toString();
+    }
+
+    public Set<CodeImport> generateImports() {
+        Set<CodeImport> imports = new HashSet<>();
+
+        imports.addAll(generateImports(simpleNamesUsed.values()));
+        imports.addAll(generateStaticImports(staticImportUsage));
+
+        return imports;
+    }
+
+    boolean processStaticImports(TypeElement element) {
+        Set<String> importedMethods = new HashSet<>();
+        List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements());
+        for (ExecutableElement method : methods) {
+            if (method.getModifiers().contains(Modifier.STATIC)) {
+                importedMethods.add(method.getSimpleName().toString());
+            }
+        }
+
+        boolean allMethodsAmbiguous = processStaticImportElements(importedMethods, this.ambiguousStaticMethods, this.declaredStaticMethods);
+
+        Set<String> importedFields = new HashSet<>();
+        List<VariableElement> fields = ElementFilter.fieldsIn(element.getEnclosedElements());
+        for (VariableElement field : fields) {
+            if (field.getModifiers().contains(Modifier.STATIC)) {
+                importedFields.add(field.getSimpleName().toString());
+            }
+        }
+
+        boolean allFieldsAmbiguous = processStaticImportElements(importedFields, this.ambiguousStaticFields, this.declaredStaticFields);
+
+        return allMethodsAmbiguous && allFieldsAmbiguous;
+    }
+
+    private static boolean processStaticImportElements(Set<String> newElements, Set<String> ambiguousElements, Set<String> declaredElements) {
+        boolean allAmbiguous = false;
+        if (declaredElements.containsAll(newElements)) {
+            // all types already declared -> we can remove the import completely -> they will all
+            // get ambiguous
+            allAmbiguous = true;
+        }
+        Set<String> newAmbiguous = new HashSet<>();
+        Set<String> newDeclared = new HashSet<>();
+
+        for (String newElement : newElements) {
+            if (declaredElements.contains(newElement)) {
+                newAmbiguous.add(newElement);
+            } else if (ambiguousElements.contains(newElement)) {
+                // nothing to do
+            } else {
+                newDeclared.add(newElement);
+            }
+        }
+
+        ambiguousElements.addAll(newAmbiguous);
+        declaredElements.addAll(newDeclared);
+        return allAmbiguous;
+    }
+
+    private boolean needsImport(Element enclosedElement, TypeMirror importType) {
+        String importPackagName = getPackageName(importType);
+        if (importPackagName == null) {
+            return false;
+        } else if (importPackagName.equals("java.lang")) {
+            return false;
+        } else if (importPackagName.equals(getPackageName(topLevelClass)) && ElementUtils.isTopLevelClass(importType)) {
+            return false; // same package name -> no import
+        }
+
+        List<Element> elements = ElementUtils.getElementHierarchy(enclosedElement);
+
+        Set<String> autoImportedTypes = new HashSet<>();
+        for (Element element : elements) {
+            if (element.getKind().isClass()) {
+                collectSuperTypeImports((TypeElement) element, autoImportedTypes);
+                collectInnerTypeImports((TypeElement) element, autoImportedTypes);
+            }
+        }
+
+        String qualifiedName = getQualifiedName(importType);
+        if (autoImportedTypes.contains(qualifiedName)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private static Set<CodeImport> generateImports(Collection<TypeMirror> toGenerate) {
+        TreeSet<CodeImport> importObjects = new TreeSet<>();
+        for (TypeMirror importType : toGenerate) {
+            importObjects.add(new CodeImport(importType, getQualifiedName(importType), false));
+        }
+        return importObjects;
+    }
+
+    private static void collectInnerTypeImports(TypeElement e, Set<String> autoImportedTypes) {
+        autoImportedTypes.add(getQualifiedName(e));
+        for (TypeElement innerClass : ElementFilter.typesIn(e.getEnclosedElements())) {
+            collectInnerTypeImports(innerClass, autoImportedTypes);
+        }
+    }
+
+    private static void collectSuperTypeImports(TypeElement e, Set<String> autoImportedTypes) {
+        List<TypeElement> superTypes = getSuperTypes(e);
+        for (TypeElement superType : superTypes) {
+            List<TypeElement> declaredTypes = getDeclaredTypes(superType);
+            for (TypeElement declaredType : declaredTypes) {
+                autoImportedTypes.add(getQualifiedName(declaredType));
+            }
+        }
+    }
+
+    private Set<CodeImport> generateStaticImports(Set<TypeMirror> toGenerate) {
+        Set<String> autoImportedStaticTypes = new HashSet<>();
+
+        // if type is declared inside a super type of this class -> no import
+        autoImportedStaticTypes.add(getQualifiedName(topLevelClass));
+        autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(topLevelClass));
+
+        TreeSet<CodeImport> importObjects = new TreeSet<>();
+        for (TypeMirror importType : toGenerate) {
+            if (getPackageName(importType) == null) {
+                continue; // no package name -> no import
+            }
+
+            String qualifiedName = getQualifiedName(importType);
+            if (autoImportedStaticTypes.contains(qualifiedName)) {
+                continue;
+            }
+
+            importObjects.add(new CodeImport(importType, qualifiedName + ".*", true));
+        }
+
+        return importObjects;
+    }
+
+    private abstract static class TypeReferenceVisitor extends CodeElementScanner<Void, Void> {
+
+        @Override
+        public void visitTree(CodeTree e, Void p) {
+            if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) {
+                visitStaticFieldReference(e, e.getType(), e.getString());
+            } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) {
+                visitStaticMethodReference(e, e.getType(), e.getString());
+            } else if (e.getType() != null) {
+                visitTypeReference(e, e.getType());
+            }
+            super.visitTree(e, p);
+        }
+
+        @Override
+        public Void visitExecutable(CodeExecutableElement e, Void p) {
+            visitAnnotations(e, e.getAnnotationMirrors());
+            if (e.getReturnType() != null) {
+                visitTypeReference(e, e.getReturnType());
+            }
+            for (TypeMirror type : e.getThrownTypes()) {
+                visitTypeReference(e, type);
+            }
+            return super.visitExecutable(e, p);
+        }
+
+        @Override
+        public Void visitType(CodeTypeElement e, Void p) {
+            visitAnnotations(e, e.getAnnotationMirrors());
+
+            visitTypeReference(e, e.getSuperclass());
+            for (TypeMirror type : e.getImplements()) {
+                visitTypeReference(e, type);
+            }
+
+            return super.visitType(e, p);
+        }
+
+        private void visitAnnotations(Element enclosingElement, List<? extends AnnotationMirror> mirrors) {
+            for (AnnotationMirror mirror : mirrors) {
+                visitAnnotation(enclosingElement, mirror);
+            }
+        }
+
+        public void visitAnnotation(Element enclosingElement, AnnotationMirror e) {
+            visitTypeReference(enclosingElement, e.getAnnotationType());
+            if (!e.getElementValues().isEmpty()) {
+                Map<? extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues();
+                Set<? extends ExecutableElement> methodsSet = values.keySet();
+                List<ExecutableElement> methodsList = new ArrayList<>();
+                for (ExecutableElement method : methodsSet) {
+                    if (values.get(method) == null) {
+                        continue;
+                    }
+                    methodsList.add(method);
+                }
+
+                for (int i = 0; i < methodsList.size(); i++) {
+                    AnnotationValue value = values.get(methodsList.get(i));
+                    visitAnnotationValue(enclosingElement, value);
+                }
+            }
+        }
+
+        public void visitAnnotationValue(Element enclosingElement, AnnotationValue e) {
+            e.accept(new AnnotationValueReferenceVisitor(enclosingElement), null);
+        }
+
+        private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7<Void, Void> {
+
+            private final Element enclosingElement;
+
+            public AnnotationValueReferenceVisitor(Element enclosedElement) {
+                this.enclosingElement = enclosedElement;
+            }
+
+            @Override
+            public Void visitBoolean(boolean b, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitByte(byte b, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitChar(char c, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitDouble(double d, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitFloat(float f, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitInt(int i, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitLong(long i, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitShort(short s, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitString(String s, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitType(TypeMirror t, Void p) {
+                visitTypeReference(enclosingElement, t);
+                return null;
+            }
+
+            @Override
+            public Void visitEnumConstant(VariableElement c, Void p) {
+                visitTypeReference(enclosingElement, c.asType());
+                return null;
+            }
+
+            @Override
+            public Void visitAnnotation(AnnotationMirror a, Void p) {
+                TypeReferenceVisitor.this.visitAnnotation(enclosingElement, a);
+                return null;
+            }
+
+            @Override
+            public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
+                for (int i = 0; i < vals.size(); i++) {
+                    TypeReferenceVisitor.this.visitAnnotationValue(enclosingElement, vals.get(i));
+                }
+                return null;
+            }
+        }
+
+        @Override
+        public Void visitVariable(VariableElement f, Void p) {
+            visitAnnotations(f, f.getAnnotationMirrors());
+            visitTypeReference(f, f.asType());
+            return super.visitVariable(f, p);
+        }
+
+        @Override
+        public void visitImport(CodeImport e, Void p) {
+        }
+
+        public abstract void visitTypeReference(Element enclosedType, TypeMirror type);
+
+        public abstract void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName);
+
+        public abstract void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName);
+
+    }
+
+    private class ImportTypeReferenceVisitor extends TypeReferenceVisitor {
+
+        @Override
+        public void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName) {
+            staticImportUsage.add(type);
+        }
+
+        @Override
+        public void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName) {
+            staticImportUsage.add(type);
+        }
+
+        @Override
+        public void visitTypeReference(Element enclosedType, TypeMirror type) {
+            createTypeReference(enclosedType, type);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CreateCastData.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+public class CreateCastData extends TemplateMethod {
+
+    private final List<String> childNames;
+
+    public CreateCastData(TemplateMethod method, List<String> childNames) {
+        super(method);
+        this.childNames = childNames;
+    }
+
+    public List<String> getChildNames() {
+        return childNames;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class ExecutableTypeData extends TemplateMethod {
+
+    private final TypeSystemData typeSystem;
+    private final TypeData type;
+
+    public ExecutableTypeData(TemplateMethod method, ExecutableElement executable, TypeSystemData typeSystem, TypeData type) {
+        super(method, executable);
+        this.typeSystem = typeSystem;
+        this.type = type;
+        if (executable.getParameters().size() < method.getMethod().getParameters().size()) {
+            throw new IllegalArgumentException(String.format("Method parameter count mismatch %s != %s.", executable.getParameters(), method.getMethod().getParameters()));
+        }
+    }
+
+    public TypeData getType() {
+        return type;
+    }
+
+    public TypeSystemData getTypeSystem() {
+        return typeSystem;
+    }
+
+    public boolean hasUnexpectedValue(ProcessorContext context) {
+        return ElementUtils.canThrowType(getMethod().getThrownTypes(), context.getTruffleTypes().getUnexpectedValueException());
+    }
+
+    public boolean isFinal() {
+        return getMethod().getModifiers().contains(Modifier.FINAL);
+    }
+
+    public boolean isAbstract() {
+        return getMethod().getModifiers().contains(Modifier.ABSTRACT);
+    }
+
+    public int getEvaluatedCount() {
+        int count = 0;
+        for (Parameter parameter : getParameters()) {
+            if (parameter.getSpecification().isSignature()) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    @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.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardData.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+public class GuardData extends TemplateMethod {
+
+    private List<GuardExpression> impliesExpressions;
+
+    public GuardData(TemplateMethod method, List<GuardExpression> impliesExpressions) {
+        super(method);
+        this.impliesExpressions = impliesExpressions;
+    }
+
+    public List<GuardExpression> getImpliesExpressions() {
+        return impliesExpressions;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof GuardData) {
+            GuardData other = (GuardData) obj;
+            return getMethod().equals(other.getMethod());
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return getMethod().hashCode();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,87 @@
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+public final class GuardExpression {
+
+    private GuardData resolvedGuard;
+
+    private final String guardName;
+    private final boolean negated;
+
+    public GuardExpression(String expression) {
+        if (expression.startsWith("!")) {
+            guardName = expression.substring(1, expression.length());
+            negated = true;
+        } else {
+            guardName = expression;
+            negated = false;
+        }
+    }
+
+    public boolean isResolved() {
+        return resolvedGuard != null;
+    }
+
+    public String getGuardName() {
+        return guardName;
+    }
+
+    public void setGuard(GuardData guard) {
+        this.resolvedGuard = guard;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof GuardExpression) {
+            GuardExpression other = (GuardExpression) obj;
+            if (isResolved() && other.isResolved()) {
+                return resolvedGuard.equals(other.resolvedGuard) && negated == other.negated;
+            } else {
+                return guardName.equals(other.guardName) && negated == other.negated;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(guardName, negated, resolvedGuard);
+    }
+
+    public final boolean implies(GuardExpression other) {
+        if (other == this) {
+            return true;
+        }
+        if (getGuardName().equals(other.getGuardName())) {
+            if (isNegated() == other.isNegated()) {
+                return true;
+            }
+        }
+
+        if (isResolved() && other.isResolved()) {
+            for (GuardExpression implies : getResolvedGuard().getImpliesExpressions()) {
+                if (implies.getGuardName().equals(other.getGuardName())) {
+                    if (implies.isNegated() == other.isNegated()) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return (negated ? "!" : "") + guardName;
+    }
+
+    public boolean isNegated() {
+        return negated;
+    }
+
+    public GuardData getResolvedGuard() {
+        return resolvedGuard;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ImplicitCastData.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+
+public class ImplicitCastData extends TemplateMethod {
+
+    private final TypeData sourceType;
+    private final TypeData targetType;
+
+    public ImplicitCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) {
+        super(method);
+        this.sourceType = sourceType;
+        this.targetType = targetType;
+    }
+
+    public TypeData getSourceType() {
+        return sourceType;
+    }
+
+    public TypeData getTargetType() {
+        return targetType;
+    }
+
+    @Override
+    public int compareTo(TemplateMethod o) {
+        if (o instanceof ImplicitCastData && sourceType != null) {
+            // implicit casts are ordered by source type since
+            // its also the order in which they are checked.
+            TypeData otherSourceType = ((ImplicitCastData) o).getSourceType();
+            if (otherSourceType != null) {
+                return this.sourceType.compareTo(otherSourceType);
+            }
+        }
+        return super.compareTo(o);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public abstract class MessageContainer implements Iterable<MessageContainer> {
+
+    private final List<Message> messages = new ArrayList<>();
+
+    public final void addWarning(String text, Object... params) {
+        getMessages().add(new Message(null, this, String.format(text, params), Kind.WARNING));
+    }
+
+    public final void addWarning(AnnotationValue value, String text, Object... params) {
+        getMessages().add(new Message(value, this, String.format(text, params), Kind.WARNING));
+    }
+
+    public final void addError(String text, Object... params) {
+        addError(null, text, params);
+    }
+
+    public final void addError(AnnotationValue value, String text, Object... params) {
+        getMessages().add(new Message(value, this, String.format(text, params), Kind.ERROR));
+    }
+
+    protected List<MessageContainer> findChildContainers() {
+        return Collections.emptyList();
+    }
+
+    public abstract Element getMessageElement();
+
+    public MessageContainer getBaseContainer() {
+        return null;
+    }
+
+    public Iterator<MessageContainer> iterator() {
+        return findChildContainers().iterator();
+    }
+
+    public final void emitMessages(ProcessorContext context, Log log) {
+        emitMessagesImpl(context, log, new HashSet<MessageContainer>(), null);
+    }
+
+    private void emitMessagesImpl(ProcessorContext context, Log log, Set<MessageContainer> visitedSinks, List<Message> verifiedMessages) {
+        List<Message> childMessages;
+        if (verifiedMessages == null) {
+            childMessages = collectMessagesWithElementChildren(new HashSet<MessageContainer>(), getMessageElement());
+        } else {
+            childMessages = verifiedMessages;
+        }
+        verifyExpectedMessages(context, log, childMessages);
+
+        for (int i = getMessages().size() - 1; i >= 0; i--) {
+            emitDefault(context, log, getMessages().get(i));
+        }
+
+        for (MessageContainer sink : findChildContainers()) {
+            if (visitedSinks.contains(sink)) {
+                continue;
+            }
+
+            visitedSinks.add(sink);
+            if (sink.getMessageElement() == this.getMessageElement()) {
+                sink.emitMessagesImpl(context, log, visitedSinks, childMessages);
+            } else {
+                sink.emitMessagesImpl(context, log, visitedSinks, null);
+            }
+        }
+    }
+
+    private List<Message> collectMessagesWithElementChildren(Set<MessageContainer> visitedSinks, Element e) {
+        if (visitedSinks.contains(this)) {
+            return Collections.emptyList();
+        }
+        visitedSinks.add(this);
+
+        List<Message> foundMessages = new ArrayList<>();
+        if (ElementUtils.typeEquals(getMessageElement().asType(), e.asType())) {
+            foundMessages.addAll(getMessages());
+        }
+        for (MessageContainer sink : findChildContainers()) {
+            foundMessages.addAll(sink.collectMessagesWithElementChildren(visitedSinks, e));
+        }
+        return foundMessages;
+    }
+
+    private void verifyExpectedMessages(ProcessorContext context, Log log, List<Message> msgs) {
+        TypeElement expectError = context.getTruffleTypes().getExpectError();
+        if (expectError != null) {
+            Element element = getMessageElement();
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(element.getAnnotationMirrors(), expectError);
+            if (mirror != null) {
+                List<String> values = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
+                if (values == null) {
+                    values = Collections.emptyList();
+                }
+                if (values.size() != msgs.size()) {
+                    log.message(Kind.ERROR, element, mirror, ElementUtils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size()));
+                }
+            }
+        }
+    }
+
+    private void emitDefault(ProcessorContext context, Log log, Message message) {
+        Kind kind = message.getKind();
+
+        Element messageElement = getMessageElement();
+        AnnotationMirror messageAnnotation = getMessageAnnotation();
+        AnnotationValue messageValue = getMessageAnnotationValue();
+        if (message.getAnnotationValue() != null) {
+            messageValue = message.getAnnotationValue();
+        }
+
+        String text = message.getText();
+
+        TypeElement expectError = context.getTruffleTypes().getExpectError();
+        if (expectError != null) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError);
+            if (mirror != null) {
+                List<String> expectedTexts = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
+                boolean found = false;
+                for (String expectedText : expectedTexts) {
+                    if (expectedText.endsWith("%") && text.startsWith(expectedText.substring(0, expectedText.length() - 1))) {
+                        found = true;
+                        break;
+                    } else if (text.equals(expectedText)) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    log.message(kind, messageElement, mirror, ElementUtils.getAnnotationValue(mirror, "value"), "Message expected one of '%s' but was '%s'.", expectedTexts, text);
+                } else {
+                    return;
+                }
+
+            }
+        }
+
+        log.message(kind, messageElement, messageAnnotation, messageValue, text);
+    }
+
+    public AnnotationMirror getMessageAnnotation() {
+        return null;
+    }
+
+    public AnnotationValue getMessageAnnotationValue() {
+        return null;
+    }
+
+    public final boolean hasErrors() {
+        return hasErrorsImpl(new HashSet<MessageContainer>());
+    }
+
+    public final List<Message> collectMessages() {
+        List<Message> collectedMessages = new ArrayList<>();
+        collectMessagesImpl(collectedMessages, new HashSet<MessageContainer>());
+        return collectedMessages;
+    }
+
+    private void collectMessagesImpl(List<Message> collectedMessages, Set<MessageContainer> visitedSinks) {
+        collectedMessages.addAll(getMessages());
+        for (MessageContainer sink : findChildContainers()) {
+            if (visitedSinks.contains(sink)) {
+                return;
+            }
+
+            visitedSinks.add(sink);
+            sink.collectMessagesImpl(collectedMessages, visitedSinks);
+        }
+    }
+
+    private boolean hasErrorsImpl(Set<MessageContainer> visitedSinks) {
+        for (Message msg : getMessages()) {
+            if (msg.getKind() == Kind.ERROR) {
+                return true;
+            }
+        }
+        for (MessageContainer sink : findChildContainers()) {
+            if (visitedSinks.contains(sink)) {
+                return false;
+            }
+
+            visitedSinks.add(sink);
+
+            if (sink.hasErrorsImpl(visitedSinks)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public List<Message> getMessages() {
+        return messages;
+    }
+
+    public static final class Message {
+
+        private final MessageContainer originalContainer;
+        private final AnnotationValue annotationValue;
+        private final String text;
+        private final Kind kind;
+
+        public Message(AnnotationValue annotationValue, MessageContainer originalContainer, String text, Kind kind) {
+            this.annotationValue = annotationValue;
+            this.originalContainer = originalContainer;
+            this.text = text;
+            this.kind = kind;
+        }
+
+        public AnnotationValue getAnnotationValue() {
+            return annotationValue;
+        }
+
+        public MessageContainer getOriginalContainer() {
+            return originalContainer;
+        }
+
+        public String getText() {
+            return text;
+        }
+
+        public Kind getKind() {
+            return kind;
+        }
+
+        @Override
+        public String toString() {
+            return kind + ": " + text;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class MethodSpec {
+
+    private final ParameterSpec returnType;
+    private final List<ParameterSpec> optional = new ArrayList<>();
+    private final List<ParameterSpec> required = new ArrayList<>();
+
+    private boolean ignoreAdditionalParameters;
+    private boolean ignoreAdditionalSpecifications;
+    private boolean variableRequiredParameters;
+
+    private List<TypeDef> typeDefinitions;
+
+    public MethodSpec(ParameterSpec returnType) {
+        this.returnType = returnType;
+    }
+
+    public void setVariableRequiredParameters(boolean variableRequiredParameters) {
+        this.variableRequiredParameters = variableRequiredParameters;
+    }
+
+    public boolean isVariableRequiredParameters() {
+        return variableRequiredParameters;
+    }
+
+    public void setIgnoreAdditionalParameters(boolean ignoreAdditionalParameter) {
+        this.ignoreAdditionalParameters = ignoreAdditionalParameter;
+    }
+
+    public boolean isIgnoreAdditionalParameters() {
+        return ignoreAdditionalParameters;
+    }
+
+    public void addOptional(ParameterSpec spec) {
+        optional.add(spec);
+    }
+
+    public ParameterSpec addRequired(ParameterSpec spec) {
+        required.add(spec);
+        return spec;
+    }
+
+    public ParameterSpec getReturnType() {
+        return returnType;
+    }
+
+    public List<ParameterSpec> getRequired() {
+        return required;
+    }
+
+    public List<ParameterSpec> getOptional() {
+        return optional;
+    }
+
+    public List<ParameterSpec> getAll() {
+        List<ParameterSpec> specs = new ArrayList<>();
+        specs.add(getReturnType());
+        specs.addAll(getOptional());
+        specs.addAll(getRequired());
+        return specs;
+    }
+
+    public ParameterSpec findParameterSpec(String name) {
+        for (ParameterSpec spec : getAll()) {
+            if (spec.getName().equals(name)) {
+                return spec;
+            }
+        }
+        return null;
+    }
+
+    public void applyTypeDefinitions(String prefix) {
+        this.typeDefinitions = createTypeDefinitions(prefix);
+    }
+
+    private List<TypeDef> createTypeDefinitions(String prefix) {
+        List<TypeDef> typeDefs = new ArrayList<>();
+
+        int defIndex = 0;
+        for (ParameterSpec spec : getAll()) {
+            List<TypeMirror> allowedTypes = spec.getAllowedTypes();
+            List<TypeMirror> types = spec.getAllowedTypes();
+            if (types != null && allowedTypes.size() > 1) {
+                TypeDef foundDef = null;
+                for (TypeDef def : typeDefs) {
+                    if (allowedTypes.equals(def.getTypes())) {
+                        foundDef = def;
+                        break;
+                    }
+                }
+                if (foundDef == null) {
+                    foundDef = new TypeDef(types, prefix + defIndex);
+                    typeDefs.add(foundDef);
+                    defIndex++;
+                }
+
+                spec.setTypeDefinition(foundDef);
+            }
+        }
+
+        return typeDefs;
+    }
+
+    public String toSignatureString(String methodName) {
+        StringBuilder b = new StringBuilder();
+        b.append("    ");
+        b.append(createTypeSignature(returnType, true));
+
+        b.append(" ");
+        b.append(methodName);
+        b.append("(");
+
+        String sep = "";
+
+        for (ParameterSpec optionalSpec : getOptional()) {
+            b.append(sep);
+            b.append("[");
+            b.append(createTypeSignature(optionalSpec, false));
+            b.append("]");
+            sep = ", ";
+        }
+
+        for (int i = 0; i < getRequired().size(); i++) {
+            ParameterSpec requiredSpec = getRequired().get(i);
+            b.append(sep);
+
+            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
+                b.append(("{"));
+            }
+            b.append(createTypeSignature(requiredSpec, false));
+            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
+                b.append(("}"));
+            }
+
+            sep = ", ";
+        }
+
+        b.append(")");
+
+        if (typeDefinitions != null && !typeDefinitions.isEmpty()) {
+            b.append("\n\n");
+
+            String lineSep = "";
+            for (TypeDef def : typeDefinitions) {
+                b.append(lineSep);
+                b.append("    <").append(def.getName()).append(">");
+                b.append(" = {");
+                String separator = "";
+                for (TypeMirror type : def.getTypes()) {
+                    b.append(separator).append(ElementUtils.getSimpleName(type));
+                    separator = ", ";
+                }
+                b.append("}");
+                lineSep = "\n";
+
+            }
+        }
+        return b.toString();
+    }
+
+    private static String createTypeSignature(ParameterSpec spec, boolean typeOnly) {
+        StringBuilder builder = new StringBuilder();
+        TypeDef foundTypeDef = spec.getTypeDefinition();
+        if (foundTypeDef != null) {
+            builder.append("<" + foundTypeDef.getName() + ">");
+        } else if (spec.getAllowedTypes().size() >= 1) {
+            builder.append(ElementUtils.getSimpleName(spec.getAllowedTypes().get(0)));
+        } else {
+            builder.append("void");
+        }
+        if (!typeOnly) {
+            builder.append(" ");
+            builder.append(spec.getName());
+        }
+        return builder.toString();
+    }
+
+    @Override
+    public String toString() {
+        return toSignatureString("methodName");
+    }
+
+    static class TypeDef {
+
+        private final List<TypeMirror> types;
+        private final String name;
+
+        private TypeDef(List<TypeMirror> types, String name) {
+            this.types = types;
+            this.name = name;
+        }
+
+        public List<TypeMirror> getTypes() {
+            return types;
+        }
+
+        public String getName() {
+            return name;
+        }
+    }
+
+    public void setIgnoreAdditionalSpecifications(boolean ignoreAdditoinalSpecifications) {
+        this.ignoreAdditionalSpecifications = ignoreAdditoinalSpecifications;
+    }
+
+    public boolean isIgnoreAdditionalSpecifications() {
+        return ignoreAdditionalSpecifications;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+
+public class NodeChildData extends MessageContainer {
+
+    public enum Cardinality {
+        ONE,
+        MANY;
+
+        public boolean isMany() {
+            return this == MANY;
+        }
+
+        public boolean isOne() {
+            return this == ONE;
+        }
+    }
+
+    private final Element sourceElement;
+    private final AnnotationMirror sourceAnnotationMirror;
+    private final String name;
+    private final TypeMirror type;
+    private final TypeMirror originalType;
+    private final Element accessElement;
+    private final Cardinality cardinality;
+
+    private List<NodeChildData> executeWith = Collections.emptyList();
+
+    private NodeData childNode;
+
+    public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality) {
+        this.sourceElement = sourceElement;
+        this.sourceAnnotationMirror = sourceMirror;
+        this.name = name;
+        this.type = nodeType;
+        this.originalType = originalNodeType;
+        this.accessElement = accessElement;
+        this.cardinality = cardinality;
+    }
+
+    public List<NodeChildData> getExecuteWith() {
+        return executeWith;
+    }
+
+    public void setExecuteWith(List<NodeChildData> executeWith) {
+        this.executeWith = executeWith;
+    }
+
+    public ExecutableTypeData findExecutableType(ProcessorContext context, TypeData targetType) {
+        ExecutableTypeData executableType = childNode.findExecutableType(targetType, getExecuteWith().size());
+        if (executableType == null) {
+            executableType = findAnyGenericExecutableType(context);
+        }
+        return executableType;
+    }
+
+    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context) {
+        return childNode.findGenericExecutableTypes(context, getExecuteWith().size());
+    }
+
+    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) {
+        return childNode.findAnyGenericExecutableType(context, getExecuteWith().size());
+    }
+
+    public TypeMirror getOriginalType() {
+        return originalType;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return sourceElement;
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return sourceAnnotationMirror;
+    }
+
+    public void setNode(NodeData nodeData) {
+        this.childNode = nodeData;
+        if (nodeData != null) {
+            getMessages().addAll(nodeData.collectMessages());
+        }
+    }
+
+    public Element getAccessElement() {
+        return accessElement;
+    }
+
+    public TypeMirror getNodeType() {
+        return type;
+    }
+
+    public Cardinality getCardinality() {
+        return cardinality;
+    }
+
+    public NodeData getNodeData() {
+        return childNode;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", node=" + getNodeData() + "]";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
+import com.oracle.truffle.dsl.processor.parser.*;
+
+public class NodeData extends Template implements Comparable<NodeData> {
+
+    private final String nodeId;
+    private final String shortName;
+    private final List<NodeData> enclosingNodes = new ArrayList<>();
+    private NodeData declaringNode;
+
+    private final TypeSystemData typeSystem;
+    private final List<NodeChildData> children;
+    private final List<NodeExecutionData> childExecutions;
+    private final List<NodeFieldData> fields;
+    private final List<String> assumptions;
+
+    private ParameterSpec instanceParameterSpec;
+
+    private final List<SpecializationData> specializations = new ArrayList<>();
+    private final List<ShortCircuitData> shortCircuits = new ArrayList<>();
+    private final List<CreateCastData> casts = new ArrayList<>();
+    private Map<Integer, List<ExecutableTypeData>> executableTypes;
+
+    private final NodeExecutionData thisExecution;
+
+    public NodeData(ProcessorContext context, TypeElement type, String shortName, TypeSystemData typeSystem, List<NodeChildData> children, List<NodeExecutionData> executions,
+                    List<NodeFieldData> fields, List<String> assumptions) {
+        super(context, type, null, null);
+        this.nodeId = type.getSimpleName().toString();
+        this.shortName = shortName;
+        this.typeSystem = typeSystem;
+        this.fields = fields;
+        this.children = children;
+        this.childExecutions = executions;
+        this.assumptions = assumptions;
+        this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, false);
+        this.thisExecution.getChild().setNode(this);
+    }
+
+    public NodeData(ProcessorContext context, TypeElement type) {
+        this(context, type, null, null, null, null, null, null);
+    }
+
+    public NodeExecutionData getThisExecution() {
+        return thisExecution;
+    }
+
+    public boolean isFallbackReachable() {
+        SpecializationData generic = getGenericSpecialization();
+        if (generic != null) {
+            return generic.isReachable();
+        }
+        return false;
+    }
+
+    public void addEnclosedNode(NodeData node) {
+        this.enclosingNodes.add(node);
+        node.declaringNode = this;
+    }
+
+    public List<NodeExecutionData> getChildExecutions() {
+        return childExecutions;
+    }
+
+    public int getSignatureSize() {
+        if (getSpecializations() != null && !getSpecializations().isEmpty()) {
+            return getSpecializations().get(0).getSignatureSize();
+        }
+        return 0;
+    }
+
+    public boolean needsFrame(ProcessorContext context) {
+        for (SpecializationData specialization : specializations) {
+            if (!specialization.isReachable()) {
+                continue;
+            }
+            if (specialization.hasFrame(context)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean isPolymorphic(ProcessorContext context) {
+        return needsRewrites(context);
+    }
+
+    public List<CreateCastData> getCasts() {
+        return casts;
+    }
+
+    public String getShortName() {
+        return shortName;
+    }
+
+    public List<NodeFieldData> getFields() {
+        return fields;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        List<MessageContainer> containerChildren = new ArrayList<>();
+        if (enclosingNodes != null) {
+            containerChildren.addAll(enclosingNodes);
+        }
+        if (typeSystem != null) {
+            containerChildren.add(typeSystem);
+        }
+        if (specializations != null) {
+            for (MessageContainer specialization : specializations) {
+                if (specialization.getMessageElement() != null) {
+                    containerChildren.add(specialization);
+                }
+            }
+        }
+        if (executableTypes != null) {
+            containerChildren.addAll(getExecutableTypes());
+        }
+        if (shortCircuits != null) {
+            containerChildren.addAll(shortCircuits);
+        }
+        if (children != null) {
+            containerChildren.addAll(children);
+        }
+        if (fields != null) {
+            containerChildren.addAll(fields);
+        }
+        if (casts != null) {
+            containerChildren.addAll(casts);
+        }
+        return containerChildren;
+    }
+
+    public ParameterSpec getInstanceParameterSpec() {
+        return instanceParameterSpec;
+    }
+
+    public void setInstanceParameterSpec(ParameterSpec instanceParameter) {
+        this.instanceParameterSpec = instanceParameter;
+    }
+
+    public String getNodeId() {
+        return nodeId;
+    }
+
+    public TypeMirror getNodeType() {
+        return getTemplateType().asType();
+    }
+
+    public List<String> getAssumptions() {
+        return assumptions;
+    }
+
+    public boolean needsFactory() {
+        if (specializations == null) {
+            return false;
+        }
+        if (getTemplateType().getModifiers().contains(Modifier.PRIVATE)) {
+            return false;
+        }
+
+        boolean noSpecialization = true;
+        for (SpecializationData specialization : specializations) {
+            noSpecialization = noSpecialization && !specialization.isSpecialized();
+        }
+        return !noSpecialization;
+    }
+
+    public boolean supportsFrame() {
+        if (executableTypes != null) {
+            for (ExecutableTypeData execType : getExecutableTypes(-1)) {
+                if (execType.findParameter("frameValue") == null) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    public List<NodeData> getNodeDeclaringChildren() {
+        List<NodeData> nodeChildren = new ArrayList<>();
+        for (NodeData child : getEnclosingNodes()) {
+            if (child.needsFactory()) {
+                nodeChildren.add(child);
+            }
+            nodeChildren.addAll(child.getNodeDeclaringChildren());
+        }
+        return nodeChildren;
+    }
+
+    public NodeData getDeclaringNode() {
+        return declaringNode;
+    }
+
+    public List<NodeData> getEnclosingNodes() {
+        return enclosingNodes;
+    }
+
+    public List<TemplateMethod> getAllTemplateMethods() {
+        List<TemplateMethod> methods = new ArrayList<>();
+
+        for (SpecializationData specialization : getSpecializations()) {
+            methods.add(specialization);
+        }
+
+        methods.addAll(getExecutableTypes());
+        methods.addAll(getShortCircuits());
+        if (getCasts() != null) {
+            methods.addAll(getCasts());
+        }
+
+        return methods;
+    }
+
+    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context, int evaluatedCount) {
+        List<ExecutableTypeData> types = findGenericExecutableTypes(context, evaluatedCount);
+        for (ExecutableTypeData type : types) {
+            if (type.getType().isGeneric()) {
+                return type;
+            }
+        }
+
+        for (ExecutableTypeData type : types) {
+            if (!type.getType().isVoid()) {
+                return type;
+            }
+        }
+
+        for (ExecutableTypeData type : types) {
+            return type;
+        }
+        return null;
+    }
+
+    public List<ExecutableTypeData> getExecutableTypes(int evaluatedCount) {
+        if (executableTypes == null) {
+            return Collections.emptyList();
+        }
+        if (evaluatedCount == -1) {
+            List<ExecutableTypeData> typeData = new ArrayList<>();
+            for (int currentEvaluationCount : executableTypes.keySet()) {
+                typeData.addAll(executableTypes.get(currentEvaluationCount));
+            }
+            return typeData;
+        } else {
+            List<ExecutableTypeData> types = executableTypes.get(evaluatedCount);
+            if (types == null) {
+                return Collections.emptyList();
+            }
+            return types;
+        }
+    }
+
+    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context, int evaluatedCount) {
+        List<ExecutableTypeData> types = new ArrayList<>();
+        for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) {
+            if (!type.hasUnexpectedValue(context)) {
+                types.add(type);
+            }
+        }
+        return types;
+    }
+
+    public ExecutableTypeData findExecutableType(TypeData prmitiveType, int evaluatedCount) {
+        for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) {
+            if (ElementUtils.typeEquals(type.getType().getPrimitiveType(), prmitiveType.getPrimitiveType())) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    public boolean needsRewrites(ProcessorContext context) {
+        boolean needsRewrites = false;
+
+        for (SpecializationData specialization : getSpecializations()) {
+            if (specialization.hasRewrite(context)) {
+                needsRewrites = true;
+                break;
+            }
+        }
+        return needsRewrites || getSpecializations().size() > 1;
+    }
+
+    public SpecializationData getPolymorphicSpecialization() {
+        for (SpecializationData specialization : specializations) {
+            if (specialization.isPolymorphic()) {
+                return specialization;
+            }
+        }
+        return null;
+    }
+
+    public SpecializationData getGenericSpecialization() {
+        for (SpecializationData specialization : specializations) {
+            if (specialization.isGeneric()) {
+                return specialization;
+            }
+        }
+        return null;
+    }
+
+    public SpecializationData getUninitializedSpecialization() {
+        for (SpecializationData specialization : specializations) {
+            if (specialization.isUninitialized()) {
+                return specialization;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public TypeSystemData getTypeSystem() {
+        return typeSystem;
+    }
+
+    public String dump() {
+        return dump(0);
+    }
+
+    private String dump(int level) {
+        String indent = "";
+        for (int i = 0; i < level; i++) {
+            indent += "    ";
+        }
+        StringBuilder builder = new StringBuilder();
+
+        builder.append(String.format("%s%s {", indent, toString()));
+
+        dumpProperty(builder, indent, "templateClass", ElementUtils.getQualifiedName(getTemplateType()));
+        dumpProperty(builder, indent, "typeSystem", getTypeSystem());
+        dumpProperty(builder, indent, "fields", getChildren());
+        dumpProperty(builder, indent, "executableTypes", getExecutableTypes());
+        dumpProperty(builder, indent, "specializations", getSpecializations());
+        dumpProperty(builder, indent, "assumptions", getAssumptions());
+        dumpProperty(builder, indent, "casts", getCasts());
+        dumpProperty(builder, indent, "messages", collectMessages());
+        if (getEnclosingNodes().size() > 0) {
+            builder.append(String.format("\n%s  children = [", indent));
+            for (NodeData node : getEnclosingNodes()) {
+                builder.append("\n");
+                builder.append(node.dump(level + 1));
+            }
+            builder.append(String.format("\n%s  ]", indent));
+        }
+        builder.append(String.format("%s}", indent));
+        return builder.toString();
+    }
+
+    private static void dumpProperty(StringBuilder b, String indent, String propertyName, Object value) {
+        if (value instanceof List) {
+            List<?> list = (List<?>) value;
+            if (!list.isEmpty()) {
+                b.append(String.format("\n%s  %s = %s", indent, propertyName, dumpList(indent, (List<?>) value)));
+            }
+        } else {
+            if (value != null) {
+                b.append(String.format("\n%s  %s = %s", indent, propertyName, value));
+            }
+        }
+    }
+
+    private static String dumpList(String indent, List<?> array) {
+        if (array == null) {
+            return "null";
+        }
+
+        if (array.isEmpty()) {
+            return "[]";
+        } else if (array.size() == 1) {
+            return "[" + array.get(0).toString() + "]";
+        }
+
+        StringBuilder b = new StringBuilder();
+        b.append("[");
+        for (Object object : array) {
+            b.append("\n        ");
+            b.append(indent);
+            b.append(object);
+            b.append(", ");
+        }
+        b.append("\n    ").append(indent).append("]");
+        return b.toString();
+    }
+
+    public NodeChildData findChild(String name) {
+        for (NodeChildData field : getChildren()) {
+            if (field.getName().equals(name)) {
+                return field;
+            }
+        }
+        return null;
+    }
+
+    public List<NodeChildData> getChildren() {
+        return children;
+    }
+
+    public List<SpecializationData> getSpecializations() {
+        return specializations;
+    }
+
+    public List<ExecutableTypeData> getExecutableTypes() {
+        return getExecutableTypes(-1);
+    }
+
+    public List<ShortCircuitData> getShortCircuits() {
+        return shortCircuits;
+    }
+
+    public void setExecutableTypes(Map<Integer, List<ExecutableTypeData>> executableTypes) {
+        this.executableTypes = executableTypes;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + getNodeId() + "]";
+    }
+
+    public CreateCastData findCast(String name) {
+        if (getCasts() != null) {
+            for (CreateCastData cast : getCasts()) {
+                if (cast.getChildNames().contains(name)) {
+                    return cast;
+                }
+            }
+        }
+        return null;
+    }
+
+    public int compareTo(NodeData o) {
+        return getNodeId().compareTo(o.getNodeId());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeFieldData.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class NodeFieldData extends MessageContainer {
+
+    private final Element messageElement;
+    private final AnnotationMirror messageAnnotation;
+    private final String name;
+    private final TypeMirror type;
+    private final boolean generated;
+    private ExecutableElement getter;
+
+    public NodeFieldData(Element messageElement, AnnotationMirror messageAnnotation, TypeMirror type, String name, boolean generated) {
+        this.messageElement = messageElement;
+        this.messageAnnotation = messageAnnotation;
+        this.name = name;
+        this.type = type;
+        this.generated = generated;
+    }
+
+    public void setGetter(ExecutableElement getter) {
+        this.getter = getter;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return messageElement;
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return messageAnnotation;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public TypeMirror getType() {
+        return type;
+    }
+
+    public boolean isGenerated() {
+        return generated;
+    }
+
+    public ExecutableElement getGetter() {
+        return getter;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public final class Parameter {
+
+    private final ParameterSpec specification;
+    private TypeData typeSystemType;
+    private TemplateMethod method;
+    private final String localName;
+    private final int specificationVarArgsIndex;
+    private final int typeVarArgsIndex;
+    private final TypeMirror actualType;
+
+    public Parameter(ParameterSpec specification, TypeMirror actualType, int specificationVarArgsIndex, int typeVarArgsIndex) {
+        this.specification = specification;
+        this.actualType = actualType;
+        this.typeSystemType = null;
+
+        this.specificationVarArgsIndex = specificationVarArgsIndex;
+
+        String valueName = specification.getName() + "Value";
+        if (specificationVarArgsIndex > -1) {
+            valueName += specificationVarArgsIndex;
+        }
+        this.typeVarArgsIndex = typeVarArgsIndex;
+        this.localName = valueName;
+    }
+
+    public Parameter(ParameterSpec specification, TypeData actualType, int specificationIndex, int varArgsIndex) {
+        this(specification, actualType.getPrimitiveType(), specificationIndex, varArgsIndex);
+        this.typeSystemType = actualType;
+    }
+
+    public Parameter(Parameter parameter, TypeData otherType) {
+        this(parameter.specification, otherType, parameter.specificationVarArgsIndex, parameter.typeVarArgsIndex);
+    }
+
+    public Parameter(Parameter parameter) {
+        this.specification = parameter.specification;
+        this.actualType = parameter.actualType;
+        this.typeSystemType = parameter.typeSystemType;
+        this.specificationVarArgsIndex = parameter.specificationVarArgsIndex;
+        this.localName = parameter.localName;
+        this.typeVarArgsIndex = parameter.typeVarArgsIndex;
+    }
+
+    public int getTypeVarArgsIndex() {
+        return typeVarArgsIndex;
+    }
+
+    public int getSpecificationVarArgsIndex() {
+        return specificationVarArgsIndex;
+    }
+
+    public String getLocalName() {
+        return localName;
+    }
+
+    void setMethod(TemplateMethod method) {
+        this.method = method;
+    }
+
+    public ParameterSpec getSpecification() {
+        return specification;
+    }
+
+    public TemplateMethod getMethod() {
+        return method;
+    }
+
+    public TypeMirror getType() {
+        return actualType;
+    }
+
+    public TypeData getTypeSystemType() {
+        return typeSystemType;
+    }
+
+    public boolean isTypeVarArgs() {
+        return typeVarArgsIndex >= 0;
+    }
+
+    public Parameter getPreviousParameter() {
+        return method.getPreviousParam(this);
+    }
+
+    @Override
+    public String toString() {
+        return ElementUtils.getSimpleName(actualType);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.MethodSpec.TypeDef;
+import com.oracle.truffle.dsl.processor.parser.*;
+
+public class ParameterSpec {
+
+    private final String name;
+    private final List<TypeMirror> allowedTypes;
+
+    /** Type is bound to local final variable. */
+    private boolean local;
+    private boolean signature;
+
+    /** Optional bound execution of node. */
+    private NodeExecutionData execution;
+    private TypeDef typeDefinition;
+
+    public ParameterSpec(String name, List<TypeMirror> allowedTypes) {
+        this.name = name;
+        this.allowedTypes = allowedTypes;
+    }
+
+    public ParameterSpec(String name, TypeMirror type) {
+        this(name, Arrays.asList(type));
+    }
+
+    public ParameterSpec(ParameterSpec o, List<TypeMirror> allowedTypes) {
+        this.name = o.name;
+        this.local = o.local;
+        this.typeDefinition = o.typeDefinition;
+        this.execution = o.execution;
+        this.signature = o.signature;
+        this.allowedTypes = allowedTypes;
+    }
+
+    public NodeExecutionData getExecution() {
+        return execution;
+    }
+
+    public void setExecution(NodeExecutionData executionData) {
+        this.execution = executionData;
+        this.signature = execution != null;
+    }
+
+    public void setSignature(boolean signature) {
+        this.signature = signature;
+    }
+
+    void setTypeDefinition(TypeDef typeDefinition) {
+        this.typeDefinition = typeDefinition;
+    }
+
+    TypeDef getTypeDefinition() {
+        return typeDefinition;
+    }
+
+    public void setLocal(boolean local) {
+        this.local = local;
+    }
+
+    public boolean isSignature() {
+        return signature;
+    }
+
+    public boolean isLocal() {
+        return local;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public List<TypeMirror> getAllowedTypes() {
+        return allowedTypes;
+    }
+
+    public boolean matches(TypeMirror actualType) {
+        for (TypeMirror mirror : allowedTypes) {
+            if (ElementUtils.typeEquals(actualType, mirror)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toSignatureString(false);
+    }
+
+    public String toSignatureString(boolean typeOnly) {
+        StringBuilder builder = new StringBuilder();
+        if (typeDefinition != null) {
+            builder.append("<" + typeDefinition.getName() + ">");
+        } else if (getAllowedTypes().size() >= 1) {
+            builder.append(ElementUtils.getSimpleName(getAllowedTypes().get(0)));
+        } else {
+            builder.append("void");
+        }
+        if (!typeOnly) {
+            builder.append(" ");
+            builder.append(getName());
+        }
+        return builder.toString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ShortCircuitData.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+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 (Parameter param : getParameters()) {
+            Parameter specializationParam = specialization.findParameter(param.getLocalName());
+            if (!ElementUtils.typeEquals(param.getType(), specializationParam.getType())) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public final class SpecializationData extends TemplateMethod {
+
+    public enum SpecializationKind {
+        UNINITIALIZED,
+        SPECIALIZED,
+        POLYMORPHIC,
+        GENERIC
+    }
+
+    private final NodeData node;
+    private final SpecializationKind kind;
+    private final List<SpecializationThrowsData> exceptions;
+    private List<GuardExpression> guards = Collections.emptyList();
+    private List<ShortCircuitData> shortCircuits;
+    private List<String> assumptions = Collections.emptyList();
+    private final Set<SpecializationData> contains = new TreeSet<>();
+    private final Set<String> containsNames = new TreeSet<>();
+    private final Set<SpecializationData> excludedBy = new TreeSet<>();
+    private String insertBeforeName;
+    private SpecializationData insertBefore;
+    private boolean reachable;
+    private int index;
+
+    public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind, List<SpecializationThrowsData> exceptions) {
+        super(template);
+        this.node = node;
+        this.kind = kind;
+        this.exceptions = exceptions;
+        this.index = template.getNaturalOrder();
+
+        for (SpecializationThrowsData exception : exceptions) {
+            exception.setSpecialization(this);
+        }
+    }
+
+    public void setInsertBefore(SpecializationData insertBefore) {
+        this.insertBefore = insertBefore;
+    }
+
+    public void setInsertBeforeName(String insertBeforeName) {
+        this.insertBeforeName = insertBeforeName;
+    }
+
+    public SpecializationData getInsertBefore() {
+        return insertBefore;
+    }
+
+    public String getInsertBeforeName() {
+        return insertBeforeName;
+    }
+
+    public Set<String> getContainsNames() {
+        return containsNames;
+    }
+
+    public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind) {
+        this(node, template, kind, new ArrayList<SpecializationThrowsData>());
+    }
+
+    public Set<SpecializationData> getContains() {
+        return contains;
+    }
+
+    public Set<SpecializationData> getExcludedBy() {
+        return excludedBy;
+    }
+
+    public void setReachable(boolean reachable) {
+        this.reachable = reachable;
+    }
+
+    public boolean isReachable() {
+        return reachable;
+    }
+
+    public boolean isPolymorphic() {
+        return kind == SpecializationKind.POLYMORPHIC;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        List<MessageContainer> sinks = new ArrayList<>();
+        if (exceptions != null) {
+            sinks.addAll(exceptions);
+        }
+        if (guards != null) {
+            for (GuardExpression guard : guards) {
+                if (guard.isResolved()) {
+                    sinks.add(guard.getResolvedGuard());
+                }
+            }
+        }
+        return sinks;
+    }
+
+    public boolean hasRewrite(ProcessorContext context) {
+        if (!getExceptions().isEmpty()) {
+            return true;
+        }
+        if (!getGuards().isEmpty()) {
+            return true;
+        }
+        if (!getAssumptions().isEmpty()) {
+            return true;
+        }
+        for (Parameter parameter : getSignatureParameters()) {
+            ExecutableTypeData type = parameter.getSpecification().getExecution().getChild().findExecutableType(context, parameter.getTypeSystemType());
+            if (type.hasUnexpectedValue(context)) {
+                return true;
+            }
+            if (type.getReturnType().getTypeSystemType().needsCastTo(parameter.getTypeSystemType())) {
+                return true;
+            }
+
+        }
+        return false;
+    }
+
+    @Override
+    public int compareTo(TemplateMethod other) {
+        if (this == other) {
+            return 0;
+        } else if (!(other instanceof SpecializationData)) {
+            return super.compareTo(other);
+        }
+        SpecializationData m2 = (SpecializationData) other;
+        int kindOrder = kind.compareTo(m2.kind);
+        if (kindOrder != 0) {
+            return kindOrder;
+        }
+
+        int compare = 0;
+        int order1 = index;
+        int order2 = m2.index;
+        if (order1 != NO_NATURAL_ORDER && order2 != NO_NATURAL_ORDER) {
+            compare = Integer.compare(order1, order2);
+            if (compare != 0) {
+                return compare;
+            }
+        }
+
+        return super.compareTo(other);
+    }
+
+    public void setIndex(int order) {
+        this.index = order;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public boolean isContainedBy(SpecializationData next) {
+        if (compareTo(next) > 0) {
+            // must be declared after the current specialization
+            return false;
+        }
+
+        Iterator<Parameter> currentSignature = getSignatureParameters().iterator();
+        Iterator<Parameter> nextSignature = next.getSignatureParameters().iterator();
+
+        while (currentSignature.hasNext() && nextSignature.hasNext()) {
+            TypeData currentType = currentSignature.next().getTypeSystemType();
+            TypeData prevType = nextSignature.next().getTypeSystemType();
+
+            if (!currentType.isImplicitSubtypeOf(prevType)) {
+                return false;
+            }
+        }
+
+        for (String nextAssumption : next.getAssumptions()) {
+            if (!getAssumptions().contains(nextAssumption)) {
+                return false;
+            }
+        }
+
+        Iterator<GuardExpression> nextGuards = next.getGuards().iterator();
+        while (nextGuards.hasNext()) {
+            GuardExpression nextGuard = nextGuards.next();
+            boolean implied = false;
+            for (GuardExpression currentGuard : getGuards()) {
+                if (currentGuard.implies(nextGuard)) {
+                    implied = true;
+                    break;
+                }
+            }
+            if (!implied) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public String createReferenceName() {
+        StringBuilder b = new StringBuilder();
+
+        b.append(getMethodName());
+        b.append("(");
+
+        String sep = "";
+        for (Parameter parameter : getParameters()) {
+            b.append(sep);
+            b.append(ElementUtils.getSimpleName(parameter.getType()));
+            sep = ", ";
+        }
+
+        b.append(")");
+        return b.toString();
+    }
+
+    public NodeData getNode() {
+        return node;
+    }
+
+    public void setGuards(List<GuardExpression> guards) {
+        this.guards = guards;
+    }
+
+    public boolean isSpecialized() {
+        return kind == SpecializationKind.SPECIALIZED;
+    }
+
+    public boolean isGeneric() {
+        return kind == SpecializationKind.GENERIC;
+    }
+
+    public boolean isUninitialized() {
+        return kind == SpecializationKind.UNINITIALIZED;
+    }
+
+    public List<SpecializationThrowsData> getExceptions() {
+        return exceptions;
+    }
+
+    public List<GuardExpression> getGuards() {
+        return guards;
+    }
+
+    public void setShortCircuits(List<ShortCircuitData> shortCircuits) {
+        this.shortCircuits = shortCircuits;
+    }
+
+    public List<ShortCircuitData> getShortCircuits() {
+        return shortCircuits;
+    }
+
+    public List<String> getAssumptions() {
+        return assumptions;
+    }
+
+    public void setAssumptions(List<String> assumptions) {
+        this.assumptions = assumptions;
+    }
+
+    public SpecializationData findNextSpecialization() {
+        List<SpecializationData> specializations = node.getSpecializations();
+        for (int i = 0; i < specializations.size() - 1; i++) {
+            if (specializations.get(i) == this) {
+                return specializations.get(i + 1);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature());
+    }
+
+    public boolean hasFrame(ProcessorContext context) {
+        for (Parameter param : getParameters()) {
+            if (ElementUtils.typeEquals(param.getType(), context.getTruffleTypes().getFrame())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean isReachableAfter(SpecializationData prev) {
+        if (!prev.isSpecialized()) {
+            return true;
+        }
+
+        if (!prev.getExceptions().isEmpty()) {
+            return true;
+        }
+
+        Iterator<Parameter> currentSignature = getSignatureParameters().iterator();
+        Iterator<Parameter> prevSignature = prev.getSignatureParameters().iterator();
+
+        while (currentSignature.hasNext() && prevSignature.hasNext()) {
+            TypeData currentType = currentSignature.next().getTypeSystemType();
+            TypeData prevType = prevSignature.next().getTypeSystemType();
+
+            if (!currentType.isImplicitSubtypeOf(prevType)) {
+                return true;
+            }
+        }
+
+        for (String prevAssumption : prev.getAssumptions()) {
+            if (!getAssumptions().contains(prevAssumption)) {
+                return true;
+            }
+        }
+
+        Iterator<GuardExpression> prevGuards = prev.getGuards().iterator();
+        Iterator<GuardExpression> currentGuards = getGuards().iterator();
+        while (prevGuards.hasNext()) {
+            GuardExpression prevGuard = prevGuards.next();
+            GuardExpression currentGuard = currentGuards.hasNext() ? currentGuards.next() : null;
+            if (currentGuard == null || !currentGuard.implies(prevGuard)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationThrowsData.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class SpecializationThrowsData extends MessageContainer {
+
+    private final AnnotationValue annotationValue;
+    private final AnnotationMirror annotationMirror;
+    private final TypeMirror javaClass;
+    private SpecializationData specialization;
+
+    public SpecializationThrowsData(AnnotationMirror annotationMirror, AnnotationValue value, TypeMirror javaClass) {
+        this.annotationMirror = annotationMirror;
+        this.annotationValue = value;
+        this.javaClass = javaClass;
+    }
+
+    void setSpecialization(SpecializationData specialization) {
+        this.specialization = specialization;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return specialization.getMessageElement();
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return annotationMirror;
+    }
+
+    @Override
+    public AnnotationValue getMessageAnnotationValue() {
+        return annotationValue;
+    }
+
+    public TypeMirror getJavaClass() {
+        return javaClass;
+    }
+
+    public SpecializationData getSpecialization() {
+        return specialization;
+    }
+
+    public AnnotationMirror getAnnotationMirror() {
+        return annotationMirror;
+    }
+
+    public SpecializationData getTransitionTo() {
+        return specialization.findNextSpecialization();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Template.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public abstract class Template extends MessageContainer {
+
+    private final ProcessorContext context;
+    private final TypeElement templateType;
+    private final String templateMethodName;
+    private final AnnotationMirror annotation;
+
+    public Template(ProcessorContext context, TypeElement templateType, String templateMethodName, AnnotationMirror annotation) {
+        this.context = context;
+        this.templateType = templateType;
+        this.templateMethodName = templateMethodName;
+        this.annotation = annotation;
+    }
+
+    public ProcessorContext getContext() {
+        return context;
+    }
+
+    @Override
+    public MessageContainer getBaseContainer() {
+        return this;
+    }
+
+    public abstract TypeSystemData getTypeSystem();
+
+    @Override
+    public Element getMessageElement() {
+        return templateType;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        return Collections.emptyList();
+    }
+
+    public String getTemplateMethodName() {
+        return templateMethodName;
+    }
+
+    public TypeElement getTemplateType() {
+        return templateType;
+    }
+
+    public AnnotationMirror getTemplateTypeAnnotation() {
+        return annotation;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + ElementUtils.getSimpleName(getTemplateType()) + "]";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,434 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.util.*;
+
+/**
+ * Note: this class has a natural ordering that is inconsistent with equals.
+ */
+public class TemplateMethod extends MessageContainer implements Comparable<TemplateMethod> {
+
+    public static final int NO_NATURAL_ORDER = -1;
+
+    private String id;
+    private final Template template;
+    private final int naturalOrder;
+    private final MethodSpec specification;
+    private final ExecutableElement method;
+    private final AnnotationMirror markerAnnotation;
+    private Parameter returnType;
+    private List<Parameter> parameters;
+
+    public TemplateMethod(String id, int naturalOrder, Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, Parameter returnType,
+                    List<Parameter> parameters) {
+        this.template = template;
+        this.specification = specification;
+        this.naturalOrder = naturalOrder;
+        this.method = method;
+        this.markerAnnotation = markerAnnotation;
+        this.returnType = returnType;
+        this.parameters = new ArrayList<>();
+        for (Parameter param : parameters) {
+            Parameter newParam = new Parameter(param);
+            this.parameters.add(newParam);
+            newParam.setMethod(this);
+        }
+        this.id = id;
+    }
+
+    public int getNaturalOrder() {
+        return naturalOrder;
+    }
+
+    public TemplateMethod(TemplateMethod method) {
+        this(method.id, method.naturalOrder, method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters);
+        getMessages().addAll(method.getMessages());
+    }
+
+    public TemplateMethod(TemplateMethod method, ExecutableElement executable) {
+        this(method.id, method.naturalOrder, method.template, method.specification, executable, method.markerAnnotation, method.returnType, method.parameters);
+        getMessages().addAll(method.getMessages());
+    }
+
+    public void setParameters(List<Parameter> parameters) {
+        this.parameters = parameters;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return method;
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return markerAnnotation;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        return Collections.emptyList();
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public Template getTemplate() {
+        return template;
+    }
+
+    public MethodSpec getSpecification() {
+        return specification;
+    }
+
+    public Parameter getReturnType() {
+        return returnType;
+    }
+
+    public void replaceParameter(String localName, Parameter newParameter) {
+        if (returnType.getLocalName().equals(localName)) {
+            returnType = newParameter;
+            returnType.setMethod(this);
+        }
+
+        for (ListIterator<Parameter> iterator = parameters.listIterator(); iterator.hasNext();) {
+            Parameter parameter = iterator.next();
+            if (parameter.getLocalName().equals(localName)) {
+                iterator.set(newParameter);
+                newParameter.setMethod(this);
+            }
+        }
+    }
+
+    public List<Parameter> getRequiredParameters() {
+        List<Parameter> requiredParameters = new ArrayList<>();
+        for (Parameter parameter : getParameters()) {
+            if (getSpecification().getRequired().contains(parameter.getSpecification())) {
+                requiredParameters.add(parameter);
+            }
+        }
+        return requiredParameters;
+    }
+
+    public Iterable<Parameter> getSignatureParameters() {
+        return new FilteredIterable<>(getParameters(), new Predicate<Parameter>() {
+            public boolean evaluate(Parameter value) {
+                return value.getSpecification().isSignature();
+            }
+        });
+    }
+
+    public List<Parameter> getParameters() {
+        return parameters;
+    }
+
+    public List<Parameter> findParameters(ParameterSpec spec) {
+        List<Parameter> foundParameters = new ArrayList<>();
+        for (Parameter param : getReturnTypeAndParameters()) {
+            if (param.getSpecification().getName().equals(spec.getName())) {
+                foundParameters.add(param);
+            }
+        }
+        return foundParameters;
+    }
+
+    public Parameter findParameter(String valueName) {
+        for (Parameter param : getReturnTypeAndParameters()) {
+            if (param.getLocalName().equals(valueName)) {
+                return param;
+            }
+        }
+        return null;
+    }
+
+    public List<Parameter> getReturnTypeAndParameters() {
+        List<Parameter> allParameters = new ArrayList<>(getParameters().size() + 1);
+        if (getReturnType() != null) {
+            allParameters.add(getReturnType());
+        }
+        allParameters.addAll(getParameters());
+        return Collections.unmodifiableList(allParameters);
+    }
+
+    public boolean canBeAccessedByInstanceOf(TypeMirror type) {
+        TypeMirror methodType = ElementUtils.findNearestEnclosingType(getMethod()).asType();
+        return ElementUtils.isAssignable(type, methodType) || ElementUtils.isAssignable(methodType, type);
+    }
+
+    public ExecutableElement getMethod() {
+        return method;
+    }
+
+    public String getMethodName() {
+        if (getMethod() != null) {
+            return getMethod().getSimpleName().toString();
+        } else {
+            return "$synthetic";
+        }
+    }
+
+    public AnnotationMirror getMarkerAnnotation() {
+        return markerAnnotation;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s [id = %s, method = %s]", getClass().getSimpleName(), getId(), getMethod());
+    }
+
+    public Parameter getPreviousParam(Parameter searchParam) {
+        Parameter prev = null;
+        for (Parameter param : getParameters()) {
+            if (param == searchParam) {
+                return prev;
+            }
+            prev = param;
+        }
+        return prev;
+    }
+
+    @SuppressWarnings("unused")
+    public int getSignatureSize() {
+        int signatureSize = 0;
+        for (Parameter parameter : getSignatureParameters()) {
+            signatureSize++;
+        }
+        return signatureSize;
+    }
+
+    public TypeSignature getTypeSignature() {
+        TypeSignature signature = new TypeSignature();
+        signature.types.add(getReturnType().getTypeSystemType());
+        for (Parameter parameter : getSignatureParameters()) {
+            TypeData typeData = parameter.getTypeSystemType();
+            if (typeData != null) {
+                signature.types.add(typeData);
+            }
+        }
+        return signature;
+    }
+
+    public Parameter getSignatureParameter(int searchIndex) {
+        int index = 0;
+        for (Parameter parameter : getParameters()) {
+            if (!parameter.getSpecification().isSignature()) {
+                continue;
+            }
+            if (index == searchIndex) {
+                return parameter;
+            }
+            index++;
+        }
+        return null;
+    }
+
+    public void updateSignature(TypeSignature signature) {
+        // TODO(CH): fails in normal usage - output ok though
+        // assert signature.size() >= 1;
+
+        int signatureIndex = 0;
+        for (Parameter parameter : getReturnTypeAndParameters()) {
+            if (!parameter.getSpecification().isSignature()) {
+                continue;
+            }
+            if (signatureIndex >= signature.size()) {
+                break;
+            }
+            TypeData newType = signature.get(signatureIndex++);
+            if (!parameter.getTypeSystemType().equals(newType)) {
+                replaceParameter(parameter.getLocalName(), new Parameter(parameter, newType));
+            }
+        }
+    }
+
+    @Override
+    public int compareTo(TemplateMethod o) {
+        if (this == o) {
+            return 0;
+        }
+
+        int compare = compareBySignature(o);
+        if (compare == 0) {
+            // if signature sorting failed sort by id
+            compare = getId().compareTo(o.getId());
+        }
+        if (compare == 0) {
+            // if still no difference sort by enclosing type name
+            TypeElement enclosingType1 = ElementUtils.findNearestEnclosingType(getMethod());
+            TypeElement enclosingType2 = ElementUtils.findNearestEnclosingType(o.getMethod());
+            compare = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString());
+        }
+        return compare;
+    }
+
+    public List<Parameter> getParametersAfter(Parameter genericParameter) {
+        boolean found = false;
+        List<Parameter> foundParameters = new ArrayList<>();
+        for (Parameter param : getParameters()) {
+            if (param.getLocalName().equals(genericParameter.getLocalName())) {
+                found = true;
+            } else if (found) {
+                foundParameters.add(param);
+            }
+        }
+        return foundParameters;
+    }
+
+    public int compareBySignature(TemplateMethod compareMethod) {
+        final TypeSystemData typeSystem = getTemplate().getTypeSystem();
+        if (typeSystem != compareMethod.getTemplate().getTypeSystem()) {
+            throw new IllegalStateException("Cannot compare two methods with different type systems.");
+        }
+
+        List<TypeMirror> signature1 = getSignatureTypes(this);
+        List<TypeMirror> signature2 = getSignatureTypes(compareMethod);
+
+        int result = 0;
+        for (int i = 0; i < Math.max(signature1.size(), signature2.size()); i++) {
+            TypeMirror t1 = i < signature1.size() ? signature1.get(i) : null;
+            TypeMirror t2 = i < signature2.size() ? signature2.get(i) : null;
+            result = compareParameter(typeSystem, t1, t2);
+            if (result != 0) {
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    protected static int compareParameter(TypeSystemData data, TypeMirror signature1, TypeMirror signature2) {
+        if (signature1 == null) {
+            return 1;
+        } else if (signature2 == null) {
+            return -1;
+        }
+
+        if (ElementUtils.typeEquals(signature1, signature2)) {
+            return 0;
+        }
+
+        int index1 = data.findType(signature1);
+        int index2 = data.findType(signature2);
+        if (index1 != -1 && index2 != -1) {
+            return index1 - index2;
+        }
+
+        // TODO this version if subclass of should be improved.
+        if (signature1.getKind() == TypeKind.DECLARED && signature2.getKind() == TypeKind.DECLARED) {
+            TypeElement element1 = ElementUtils.fromTypeMirror(signature1);
+            TypeElement element2 = ElementUtils.fromTypeMirror(signature2);
+
+            if (ElementUtils.getDirectSuperTypes(element1).contains(element2)) {
+                return -1;
+            } else if (ElementUtils.getDirectSuperTypes(element2).contains(element1)) {
+                return 1;
+            }
+        }
+        return ElementUtils.getSimpleName(signature1).compareTo(ElementUtils.getSimpleName(signature2));
+    }
+
+    public static List<TypeMirror> getSignatureTypes(TemplateMethod method) {
+        List<TypeMirror> types = new ArrayList<>();
+        for (Parameter param : method.getSignatureParameters()) {
+            types.add(param.getType());
+        }
+        return types;
+    }
+
+    public static class TypeSignature implements Iterable<TypeData>, Comparable<TypeSignature> {
+
+        private final List<TypeData> types;
+
+        public TypeSignature() {
+            this.types = new ArrayList<>();
+        }
+
+        public TypeSignature(List<TypeData> signature) {
+            this.types = signature;
+        }
+
+        @Override
+        public int hashCode() {
+            return types.hashCode();
+        }
+
+        public int size() {
+            return types.size();
+        }
+
+        public TypeData get(int index) {
+            return types.get(index);
+        }
+
+        public int compareTo(TypeSignature other) {
+            if (this == other) {
+                return 0;
+            } else if (types.size() != other.types.size()) {
+                return types.size() - other.types.size();
+            } else if (types.isEmpty()) {
+                return 0;
+            }
+
+            for (int i = 0; i < types.size(); i++) {
+                TypeData type1 = types.get(i);
+                TypeData type2 = other.types.get(i);
+
+                int comparison = type1.compareTo(type2);
+                if (comparison != 0) {
+                    return comparison;
+                }
+            }
+
+            return 0;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof TypeSignature) {
+                return ((TypeSignature) obj).types.equals(types);
+            }
+            return super.equals(obj);
+        }
+
+        public Iterator<TypeData> iterator() {
+            return types.iterator();
+        }
+
+        @Override
+        public String toString() {
+            return types.toString();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethodParser.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public abstract class TemplateMethodParser<T extends Template, E extends TemplateMethod> {
+
+    private final ProcessorContext context;
+
+    protected final T template;
+
+    private boolean emitErrors = true;
+    private boolean parseNullOnError = false;
+    private boolean useVarArgs = false;
+
+    public TemplateMethodParser(ProcessorContext context, T template) {
+        this.template = template;
+        this.context = context;
+    }
+
+    protected void setUseVarArgs(boolean useVarArgs) {
+        this.useVarArgs = useVarArgs;
+    }
+
+    public boolean isUseVarArgs() {
+        return useVarArgs;
+    }
+
+    public boolean isEmitErrors() {
+        return emitErrors;
+    }
+
+    public void setParseNullOnError(boolean nullOnError) {
+        this.parseNullOnError = nullOnError;
+    }
+
+    public boolean isParseNullOnError() {
+        return parseNullOnError;
+    }
+
+    public void setEmitErrors(boolean emitErrors) {
+        this.emitErrors = emitErrors;
+    }
+
+    public ProcessorContext getContext() {
+        return context;
+    }
+
+    public TypeSystemData getTypeSystem() {
+        return template.getTypeSystem();
+    }
+
+    public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror);
+
+    public abstract E create(TemplateMethod method, boolean invalid);
+
+    public abstract boolean isParsable(ExecutableElement method);
+
+    public Class<? extends Annotation> getAnnotationType() {
+        return null;
+    }
+
+    public final List<E> parse(List<? extends Element> elements) {
+        List<ExecutableElement> methods = new ArrayList<>();
+        methods.addAll(ElementFilter.methodsIn(elements));
+
+        List<E> parsedMethods = new ArrayList<>();
+        boolean valid = true;
+        int naturalOrder = 0;
+        for (ExecutableElement method : methods) {
+            if (!isParsable(method)) {
+                continue;
+            }
+
+            Class<? extends Annotation> annotationType = getAnnotationType();
+            AnnotationMirror mirror = null;
+            if (annotationType != null) {
+                mirror = ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType);
+            }
+
+            E parsedMethod = parse(naturalOrder, method, mirror);
+
+            if (method.getModifiers().contains(Modifier.PRIVATE) && emitErrors) {
+                parsedMethod.addError("Method annotated with @%s must not be private.", getAnnotationType().getSimpleName());
+                parsedMethods.add(parsedMethod);
+                valid = false;
+                continue;
+            }
+
+            if (parsedMethod != null) {
+                parsedMethods.add(parsedMethod);
+            } else {
+                valid = false;
+            }
+            naturalOrder++;
+        }
+        Collections.sort(parsedMethods);
+
+        if (!valid && parseNullOnError) {
+            return null;
+        }
+        return parsedMethods;
+    }
+
+    private E parse(int naturalOrder, ExecutableElement method, AnnotationMirror annotation) {
+        MethodSpec methodSpecification = createSpecification(method, annotation);
+        if (methodSpecification == null) {
+            return null;
+        }
+
+        methodSpecification.applyTypeDefinitions("types");
+
+        String id = method.getSimpleName().toString();
+        TypeMirror returnType = method.getReturnType();
+        List<TypeMirror> parameterTypes = new ArrayList<>();
+        for (VariableElement var : method.getParameters()) {
+            parameterTypes.add(var.asType());
+        }
+
+        return parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, parameterTypes);
+    }
+
+    private E parseImpl(MethodSpec methodSpecification, int naturalOrder, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType, List<TypeMirror> parameterTypes) {
+        ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
+        Parameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, -1, -1);
+        if (returnTypeMirror == null) {
+            if (emitErrors) {
+                E invalidMethod = create(new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<Parameter> emptyList()), true);
+                String expectedReturnType = returnTypeSpec.toSignatureString(true);
+                String actualReturnType = ElementUtils.getSimpleName(returnType);
+
+                String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
+                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
+                invalidMethod.addError(message);
+                return invalidMethod;
+            } else {
+                return null;
+            }
+        }
+
+        List<Parameter> parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method != null ? method.isVarArgs() : false);
+        if (parameters == null) {
+            if (isEmitErrors() && method != null) {
+                E invalidMethod = create(new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<Parameter> emptyList()), true);
+                String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(method),
+                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
+                invalidMethod.addError(message);
+                return invalidMethod;
+            } else {
+                return null;
+            }
+        }
+
+        return create(new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, parameters), false);
+    }
+
+    private static String createActualSignature(ExecutableElement method) {
+        StringBuilder b = new StringBuilder("(");
+        String sep = "";
+        if (method != null) {
+            for (VariableElement var : method.getParameters()) {
+                b.append(sep);
+                b.append(ElementUtils.getSimpleName(var.asType()));
+                sep = ", ";
+            }
+        }
+        b.append(")");
+        return b.toString();
+    }
+
+    /*
+     * Parameter parsing tries to parse required arguments starting from offset 0 with increasing
+     * offset until it finds a signature end that matches the required specification. If there is no
+     * end matching the required arguments, parsing fails. Parameters prior to the parsed required
+     * ones are cut and used to parse the optional parameters.
+     */
+    private List<Parameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes, boolean varArgs) {
+        List<Parameter> parsedRequired = null;
+        int offset = 0;
+        for (; offset <= parameterTypes.size(); offset++) {
+            List<TypeMirror> parameters = new ArrayList<>();
+            parameters.addAll(parameterTypes.subList(offset, parameterTypes.size()));
+            parsedRequired = parseParametersRequired(spec, parameters, varArgs);
+            if (parsedRequired != null) {
+                break;
+            }
+        }
+
+        if (parsedRequired == null) {
+            return null;
+        }
+
+        if (parsedRequired.isEmpty() && offset == 0) {
+            offset = parameterTypes.size();
+        }
+        List<TypeMirror> potentialOptionals = parameterTypes.subList(0, offset);
+        List<Parameter> parsedOptionals = parseParametersOptional(spec, potentialOptionals);
+        if (parsedOptionals == null) {
+            return null;
+        }
+
+        List<Parameter> finalParameters = new ArrayList<>();
+        finalParameters.addAll(parsedOptionals);
+        finalParameters.addAll(parsedRequired);
+        return finalParameters;
+    }
+
+    private List<Parameter> parseParametersOptional(MethodSpec spec, List<TypeMirror> types) {
+        List<Parameter> parsedParams = new ArrayList<>();
+
+        int typeStartIndex = 0;
+        List<ParameterSpec> specifications = spec.getOptional();
+        outer: for (int specIndex = 0; specIndex < specifications.size(); specIndex++) {
+            ParameterSpec specification = specifications.get(specIndex);
+            for (int typeIndex = typeStartIndex; typeIndex < types.size(); typeIndex++) {
+                TypeMirror actualType = types.get(typeIndex);
+                Parameter optionalParam = matchParameter(specification, actualType, -1, -1);
+                if (optionalParam != null) {
+                    parsedParams.add(optionalParam);
+                    typeStartIndex = typeIndex + 1;
+                    continue outer;
+                }
+            }
+        }
+
+        if (typeStartIndex < types.size()) {
+            // not enough types found
+            return null;
+        }
+        return parsedParams;
+    }
+
+    private List<Parameter> parseParametersRequired(MethodSpec spec, List<TypeMirror> types, boolean typeVarArgs) {
+        List<Parameter> parsedParams = new ArrayList<>();
+        List<ParameterSpec> specifications = spec.getRequired();
+        boolean specVarArgs = spec.isVariableRequiredParameters();
+        int typeIndex = 0;
+        int specificationIndex = 0;
+
+        ParameterSpec specification;
+        while ((specification = nextSpecification(specifications, specificationIndex, specVarArgs)) != null) {
+            TypeMirror actualType = nextActualType(types, typeIndex, typeVarArgs);
+            if (actualType == null) {
+                if (spec.isIgnoreAdditionalSpecifications()) {
+                    break;
+                }
+                return null;
+            }
+
+            int typeVarArgsIndex = typeVarArgs ? typeIndex - types.size() + 1 : -1;
+            int specVarArgsIndex = specVarArgs ? specificationIndex - specifications.size() + 1 : -1;
+
+            if (typeVarArgsIndex >= 0 && specVarArgsIndex >= 0) {
+                // both specifications and types have a variable number of arguments
+                // we would get into an endless loop if we would continue
+                break;
+            }
+
+            Parameter resolvedParameter = matchParameter(specification, actualType, specVarArgsIndex, typeVarArgsIndex);
+            if (resolvedParameter == null) {
+                return null;
+            }
+            parsedParams.add(resolvedParameter);
+            typeIndex++;
+            specificationIndex++;
+        }
+
+        if (typeIndex < types.size()) {
+            // additional types available
+            if (spec.isIgnoreAdditionalParameters()) {
+                return parsedParams;
+            } else {
+                return null;
+            }
+        }
+
+        return parsedParams;
+    }
+
+    private static ParameterSpec nextSpecification(List<ParameterSpec> specifications, int specIndex, boolean varArgs) {
+        if (varArgs && specIndex >= specifications.size() - 1 && !specifications.isEmpty()) {
+            return specifications.get(specifications.size() - 1);
+        } else if (specIndex < specifications.size()) {
+            return specifications.get(specIndex);
+        } else {
+            return null;
+        }
+    }
+
+    private static TypeMirror nextActualType(List<TypeMirror> types, int typeIndex, boolean varArgs) {
+        if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) {
+            // unpack varargs array argument
+            TypeMirror actualType = types.get(types.size() - 1);
+            if (actualType.getKind() == TypeKind.ARRAY) {
+                actualType = ((ArrayType) actualType).getComponentType();
+            }
+            return actualType;
+        } else if (typeIndex < types.size()) {
+            return types.get(typeIndex);
+        } else {
+            return null;
+        }
+    }
+
+    private Parameter matchParameter(ParameterSpec specification, TypeMirror mirror, int specificationIndex, int varArgsIndex) {
+        TypeMirror resolvedType = mirror;
+        if (hasError(resolvedType)) {
+            return null;
+        }
+
+        if (!specification.matches(resolvedType)) {
+            return null;
+        }
+
+        TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType);
+        if (resolvedTypeData != null) {
+            return new Parameter(specification, resolvedTypeData, specificationIndex, varArgsIndex);
+        } else {
+            return new Parameter(specification, resolvedType, specificationIndex, varArgsIndex);
+        }
+    }
+
+    public final E create(String id, int naturalOrder, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List<TypeMirror> parameterTypes) {
+        return parseImpl(createSpecification(methodMetadata, mirror), naturalOrder, id, methodMetadata, mirror, returnType, parameterTypes);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCastData.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+
+public class TypeCastData extends TemplateMethod {
+
+    private final TypeData targetType;
+    private final TypeData sourceType;
+
+    public TypeCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) {
+        super(method);
+        this.sourceType = sourceType;
+        this.targetType = targetType;
+    }
+
+    public boolean isGeneric() {
+        return sourceType.isGeneric();
+    }
+
+    public TypeData getSourceType() {
+        return sourceType;
+    }
+
+    public TypeData getTargetType() {
+        return targetType;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCheckData.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+
+public class TypeCheckData extends TemplateMethod {
+
+    private final TypeData checkedType;
+    private final TypeData valueType;
+
+    public TypeCheckData(TemplateMethod method, TypeData checkedType, TypeData valueType) {
+        super(method);
+        this.checkedType = checkedType;
+        this.valueType = valueType;
+    }
+
+    public boolean isGeneric() {
+        return valueType.isGeneric();
+    }
+
+    public TypeData getCheckedType() {
+        return checkedType;
+    }
+
+    public TypeData getValueType() {
+        return valueType;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeData.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class TypeData extends MessageContainer implements Comparable<TypeData> {
+
+    private final TypeSystemData typeSystem;
+    private final AnnotationValue annotationValue;
+    private final TypeMirror primitiveType;
+    private final TypeMirror boxedType;
+
+    private final int index;
+    private final List<TypeCastData> typeCasts = new ArrayList<>();
+    private final List<TypeCheckData> typeChecks = new ArrayList<>();
+
+    public TypeData(TypeSystemData typeSystem, int index, AnnotationValue value, TypeMirror primitiveType, TypeMirror boxedType) {
+        this.index = index;
+        this.typeSystem = typeSystem;
+        this.annotationValue = value;
+        this.primitiveType = primitiveType;
+        this.boxedType = boxedType;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return typeSystem.getMessageElement();
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return typeSystem.getMessageAnnotation();
+    }
+
+    @Override
+    public AnnotationValue getMessageAnnotationValue() {
+        return annotationValue;
+    }
+
+    public void addTypeCast(TypeCastData typeCast) {
+        this.typeCasts.add(typeCast);
+    }
+
+    public void addTypeCheck(TypeCheckData typeCheck) {
+        this.typeChecks.add(typeCheck);
+    }
+
+    public List<TypeCastData> getTypeCasts() {
+        return typeCasts;
+    }
+
+    public List<TypeCheckData> getTypeChecks() {
+        return typeChecks;
+    }
+
+    public TypeSystemData getTypeSystem() {
+        return typeSystem;
+    }
+
+    public TypeMirror getPrimitiveType() {
+        return primitiveType;
+    }
+
+    public TypeMirror getBoxedType() {
+        return boxedType;
+    }
+
+    public boolean isGeneric() {
+        return ElementUtils.typeEquals(boxedType, getTypeSystem().getGenericType());
+    }
+
+    public boolean isVoid() {
+        if (getTypeSystem().getVoidType() == null) {
+            return false;
+        }
+        return ElementUtils.typeEquals(boxedType, getTypeSystem().getVoidType().getBoxedType());
+    }
+
+    public int compareTo(TypeData o) {
+        if (this.equals(o)) {
+            return 0;
+        }
+        return index - o.index;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(index, primitiveType);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof TypeData)) {
+            return false;
+        }
+        TypeData otherType = (TypeData) obj;
+        return index == otherType.index && ElementUtils.typeEquals(primitiveType, otherType.primitiveType);
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + ElementUtils.getSimpleName(primitiveType) + "]";
+    }
+
+    public boolean equalsType(TypeData actualTypeData) {
+        return ElementUtils.typeEquals(boxedType, actualTypeData.boxedType);
+    }
+
+    public boolean needsCastTo(TypeData targetType) {
+        return ElementUtils.needsCastTo(getPrimitiveType(), targetType.getPrimitiveType());
+    }
+
+    public boolean needsCastTo(TypeMirror targetType) {
+        return ElementUtils.needsCastTo(getPrimitiveType(), targetType);
+    }
+
+    public boolean isPrimitive() {
+        return ElementUtils.isPrimitive(getPrimitiveType());
+    }
+
+    public boolean isImplicitSubtypeOf(TypeData other) {
+        List<ImplicitCastData> casts = other.getTypeSystem().lookupByTargetType(other);
+        for (ImplicitCastData cast : casts) {
+            if (isSubtypeOf(cast.getSourceType())) {
+                return true;
+            }
+        }
+        return isSubtypeOf(other);
+    }
+
+    public boolean isSubtypeOf(TypeData other) {
+        return ElementUtils.isSubtype(boxedType, other.boxedType);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class TypeSystemData extends Template {
+
+    private List<TypeData> types;
+    private List<TypeMirror> primitiveTypeMirrors = new ArrayList<>();
+    private List<TypeMirror> boxedTypeMirrors = new ArrayList<>();
+
+    private List<ImplicitCastData> implicitCasts;
+    private List<TypeCastData> casts;
+    private List<TypeCheckData> checks;
+
+    private TypeMirror genericType;
+    private TypeData voidType;
+
+    public TypeSystemData(ProcessorContext context, TypeElement templateType, AnnotationMirror annotation) {
+        super(context, templateType, null, annotation);
+    }
+
+    @Override
+    public TypeSystemData getTypeSystem() {
+        return this;
+    }
+
+    public void setTypes(List<TypeData> types) {
+        this.types = types;
+        if (types != null) {
+            for (TypeData typeData : types) {
+                primitiveTypeMirrors.add(typeData.getPrimitiveType());
+                boxedTypeMirrors.add(typeData.getBoxedType());
+            }
+        }
+    }
+
+    public void setImplicitCasts(List<ImplicitCastData> implicitCasts) {
+        this.implicitCasts = implicitCasts;
+    }
+
+    public List<ImplicitCastData> getImplicitCasts() {
+        return implicitCasts;
+    }
+
+    public void setCasts(List<TypeCastData> casts) {
+        this.casts = casts;
+    }
+
+    public void setChecks(List<TypeCheckData> checks) {
+        this.checks = checks;
+    }
+
+    public void setGenericType(TypeMirror genericType) {
+        this.genericType = genericType;
+    }
+
+    public void setVoidType(TypeData voidType) {
+        this.voidType = voidType;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        List<MessageContainer> sinks = new ArrayList<>();
+        if (types != null) {
+            sinks.addAll(types);
+        }
+        if (checks != null) {
+            sinks.addAll(checks);
+        }
+        if (casts != null) {
+            sinks.addAll(casts);
+        }
+        if (implicitCasts != null) {
+            sinks.addAll(implicitCasts);
+        }
+        return sinks;
+    }
+
+    public TypeData getVoidType() {
+        return voidType;
+    }
+
+    public List<TypeMirror> getBoxedTypeMirrors() {
+        return boxedTypeMirrors;
+    }
+
+    public List<TypeMirror> getPrimitiveTypeMirrors() {
+        return primitiveTypeMirrors;
+    }
+
+    public List<TypeData> getTypes() {
+        return types;
+    }
+
+    public TypeMirror getGenericType() {
+        return genericType;
+    }
+
+    public TypeData getGenericTypeData() {
+        TypeData result = types.get(types.size() - 1);
+        assert result.getBoxedType() == genericType;
+        return result;
+    }
+
+    public TypeData findType(String simpleName) {
+        for (TypeData type : types) {
+            if (ElementUtils.getSimpleName(type.getBoxedType()).equals(simpleName)) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    public TypeData findTypeData(TypeMirror type) {
+        if (ElementUtils.typeEquals(voidType.getPrimitiveType(), type)) {
+            return voidType;
+        }
+
+        int index = findType(type);
+        if (index == -1) {
+            return null;
+        }
+        return types.get(index);
+    }
+
+    public int findType(TypeMirror type) {
+        for (int i = 0; i < types.size(); i++) {
+            if (ElementUtils.typeEquals(types.get(i).getPrimitiveType(), type)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[template = " + ElementUtils.getSimpleName(getTemplateType()) + ", types = " + types + "]";
+    }
+
+    public List<ImplicitCastData> lookupByTargetType(TypeData targetType) {
+        if (getImplicitCasts() == null) {
+            return Collections.emptyList();
+        }
+        List<ImplicitCastData> foundCasts = new ArrayList<>();
+        for (ImplicitCastData cast : getImplicitCasts()) {
+            if (cast.getTargetType().equals(targetType)) {
+                foundCasts.add(cast);
+            }
+        }
+        return foundCasts;
+    }
+
+    public ImplicitCastData lookupCast(TypeData sourceType, TypeData targetType) {
+        if (getImplicitCasts() == null) {
+            return null;
+        }
+        for (ImplicitCastData cast : getImplicitCasts()) {
+            if (cast.getSourceType().equals(sourceType) && cast.getTargetType().equals(targetType)) {
+                return cast;
+            }
+        }
+        return null;
+    }
+
+    public List<TypeData> lookupSourceTypes(TypeData type) {
+        List<TypeData> sourceTypes = new ArrayList<>();
+        sourceTypes.add(type);
+        if (getImplicitCasts() != null) {
+            for (ImplicitCastData cast : getImplicitCasts()) {
+                if (cast.getTargetType() == type) {
+                    sourceTypes.add(cast.getSourceType());
+                }
+            }
+        }
+        Collections.sort(sourceTypes);
+        return sourceTypes;
+    }
+
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.util.*;
-
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class CreateCastData extends TemplateMethod {
-
-    private final List<String> childNames;
-
-    public CreateCastData(TemplateMethod method, List<String> childNames) {
-        super(method);
-        this.childNames = childNames;
-    }
-
-    public List<String> getChildNames() {
-        return childNames;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class CreateCastParser extends NodeMethodParser<CreateCastData> {
-
-    public CreateCastParser(ProcessorContext context, NodeData operation) {
-        super(context, operation);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return CreateCast.class;
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        List<String> childNames = Utils.getAnnotationValueList(String.class, mirror, "value");
-        NodeChildData foundChild = null;
-        for (String childName : childNames) {
-            foundChild = getNode().findChild(childName);
-            if (foundChild != null) {
-                break;
-            }
-        }
-        TypeMirror baseType = getContext().getTruffleTypes().getNode();
-        if (foundChild != null) {
-            baseType = foundChild.getOriginalType();
-        }
-
-        MethodSpec spec = new MethodSpec(new InheritsParameterSpec("child", baseType));
-        addDefaultFieldMethodSpec(spec);
-        ParameterSpec childSpec = new ParameterSpec("castedChild", baseType);
-        childSpec.setSignature(true);
-        spec.addRequired(childSpec);
-        return spec;
-    }
-
-    @Override
-    public CreateCastData create(TemplateMethod method, boolean invalid) {
-        AnnotationMirror mirror = method.getMarkerAnnotation();
-        List<String> childNames = Utils.getAnnotationValueList(String.class, mirror, "value");
-        CreateCastData cast = new CreateCastData(method, childNames);
-        AnnotationValue value = Utils.getAnnotationValue(mirror, "value");
-        TypeMirror type = null;
-        if (childNames == null || childNames.isEmpty()) {
-            cast.addError(value, "No value specified but required.");
-            return cast;
-        }
-
-        for (String childName : childNames) {
-            NodeChildData child = getNode().findChild(childName);
-            if (child == null) {
-                // error
-                cast.addError(value, "Specified child '%s' not found.", childName);
-                continue;
-            }
-            if (type == null) {
-                type = child.getNodeType();
-            } else if (!Utils.typeEquals(type, child.getNodeType())) {
-                cast.addError(value, "All child nodes for a cast must have the same node type.");
-                continue;
-            }
-        }
-        return cast;
-    }
-
-    private static class InheritsParameterSpec extends ParameterSpec {
-
-        public InheritsParameterSpec(String name, TypeMirror... allowedTypes) {
-            super(name, Arrays.asList(allowedTypes));
-        }
-
-        @Override
-        public boolean matches(TypeMirror actualType) {
-            boolean found = false;
-            for (TypeMirror specType : getAllowedTypes()) {
-                if (Utils.isAssignable(actualType, specType)) {
-                    found = true;
-                    break;
-                }
-            }
-            return found;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class ExecutableTypeData extends TemplateMethod {
-
-    private final TypeSystemData typeSystem;
-    private final TypeData type;
-
-    public ExecutableTypeData(TemplateMethod method, ExecutableElement executable, TypeSystemData typeSystem, TypeData type) {
-        super(method, executable);
-        this.typeSystem = typeSystem;
-        this.type = type;
-        if (executable.getParameters().size() < method.getMethod().getParameters().size()) {
-            throw new IllegalArgumentException(String.format("Method parameter count mismatch %s != %s.", executable.getParameters(), method.getMethod().getParameters()));
-        }
-    }
-
-    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);
-    }
-
-    public boolean isAbstract() {
-        return getMethod().getModifiers().contains(Modifier.ABSTRACT);
-    }
-
-    public int getEvaluatedCount() {
-        int count = 0;
-        for (ActualParameter parameter : getParameters()) {
-            if (parameter.getSpecification().isSignature()) {
-                count++;
-            }
-        }
-        return count;
-    }
-
-    @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);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class ExecutableTypeMethodParser extends NodeMethodParser<ExecutableTypeData> {
-
-    public ExecutableTypeMethodParser(ProcessorContext context, NodeData node) {
-        super(context, node);
-        setEmitErrors(false);
-        setParseNullOnError(false);
-        setUseVarArgs(true);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null);
-        List<ParameterSpec> requiredSpecs = new ArrayList<>(spec.getRequired());
-        spec.getRequired().clear();
-
-        List<TypeMirror> allowedTypes = getNode().getTypeSystem().getPrimitiveTypeMirrors();
-        for (ParameterSpec originalSpec : requiredSpecs) {
-            spec.addRequired(new ParameterSpec(originalSpec, allowedTypes));
-        }
-        spec.setIgnoreAdditionalSpecifications(true);
-        spec.setIgnoreAdditionalParameters(true);
-        spec.setVariableRequiredParameters(true);
-        // varargs
-        ParameterSpec otherParameters = new ParameterSpec("other", allowedTypes);
-        otherParameters.setSignature(true);
-        spec.addRequired(otherParameters);
-        return spec;
-    }
-
-    @Override
-    public final boolean isParsable(ExecutableElement method) {
-        if (method.getModifiers().contains(Modifier.STATIC)) {
-            return false;
-        } else if (method.getModifiers().contains(Modifier.NATIVE)) {
-            return false;
-        }
-        return method.getSimpleName().toString().startsWith("execute");
-    }
-
-    @Override
-    protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
-        List<TypeMirror> types = new ArrayList<>(getNode().getTypeSystem().getPrimitiveTypeMirrors());
-        types.add(getNode().getTypeSystem().getVoidType().getPrimitiveType());
-        return types;
-    }
-
-    @Override
-    public ExecutableTypeData create(TemplateMethod method, boolean invalid) {
-        TypeData resolvedType = method.getReturnType().getTypeSystemType();
-        return new ExecutableTypeData(method, method.getMethod(), getNode().getTypeSystem(), resolvedType);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return null;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.SpecializationData.SpecializationKind;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class GenericParser extends NodeMethodParser<SpecializationData> {
-
-    public GenericParser(ProcessorContext context, NodeData node) {
-        super(context, node);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        return createDefaultMethodSpec(method, mirror, true, null);
-    }
-
-    @Override
-    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
-        List<ExecutableTypeData> execTypes = execution.getChild().findGenericExecutableTypes(getContext());
-        List<TypeMirror> types = new ArrayList<>();
-        for (ExecutableTypeData type : execTypes) {
-            types.add(type.getType().getPrimitiveType());
-        }
-        ParameterSpec spec = new ParameterSpec(execution.getName(), types);
-        spec.setExecution(execution);
-        return spec;
-    }
-
-    @Override
-    public SpecializationData create(TemplateMethod method, boolean invalid) {
-        return new SpecializationData(getNode(), method, SpecializationKind.GENERIC);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return Generic.class;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class NodeChildData extends MessageContainer {
-
-    public enum Cardinality {
-        ONE,
-        MANY;
-
-        public boolean isMany() {
-            return this == MANY;
-        }
-
-        public boolean isOne() {
-            return this == ONE;
-        }
-    }
-
-    private NodeData parentNode;
-    private final Element sourceElement;
-    private final AnnotationMirror sourceAnnotationMirror;
-    private final String name;
-    private final TypeMirror type;
-    private final TypeMirror originalType;
-    private final Element accessElement;
-    private final Cardinality cardinality;
-
-    private List<NodeChildData> executeWith = Collections.emptyList();
-
-    private NodeData childNode;
-
-    public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality) {
-        this.sourceElement = sourceElement;
-        this.sourceAnnotationMirror = sourceMirror;
-        this.name = name;
-        this.type = nodeType;
-        this.originalType = originalNodeType;
-        this.accessElement = accessElement;
-        this.cardinality = cardinality;
-    }
-
-    void setParentNode(NodeData parentNode) {
-        this.parentNode = parentNode;
-    }
-
-    public List<NodeChildData> getExecuteWith() {
-        return executeWith;
-    }
-
-    void setExecuteWith(List<NodeChildData> executeWith) {
-        this.executeWith = executeWith;
-    }
-
-    public boolean needsImplicitCast(ProcessorContext context) {
-        if (!parentNode.needsRewrites(context)) {
-            return false;
-        }
-
-        boolean used = false;
-        for (NodeExecutionData execution : parentNode.getChildExecutions()) {
-            if (execution.getChild() == this) {
-                used = true;
-                break;
-            }
-        }
-        if (!used) {
-            return false;
-        }
-
-        return getNodeData().getTypeSystem().getImplicitCasts() != null && !getNodeData().getTypeSystem().getImplicitCasts().isEmpty();
-    }
-
-    public ExecutableTypeData findExecutableType(ProcessorContext context, TypeData targetType) {
-        ExecutableTypeData executableType = childNode.findExecutableType(targetType, getExecuteWith().size());
-        if (executableType == null) {
-            executableType = findAnyGenericExecutableType(context);
-        }
-        return executableType;
-    }
-
-    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context) {
-        return childNode.findGenericExecutableTypes(context, getExecuteWith().size());
-    }
-
-    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) {
-        return childNode.findAnyGenericExecutableType(context, getExecuteWith().size());
-    }
-
-    public List<ExecutableTypeData> findExecutableTypes() {
-        return childNode.getExecutableTypes(getExecuteWith().size());
-    }
-
-    public TypeMirror getOriginalType() {
-        return originalType;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return sourceElement;
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return sourceAnnotationMirror;
-    }
-
-    void setNode(NodeData nodeData) {
-        this.childNode = nodeData;
-        if (nodeData != null) {
-            getMessages().addAll(nodeData.collectMessages());
-        }
-    }
-
-    public Element getAccessElement() {
-        return accessElement;
-    }
-
-    public TypeMirror getNodeType() {
-        return type;
-    }
-
-    public Cardinality getCardinality() {
-        return cardinality;
-    }
-
-    public NodeData getNodeData() {
-        return childNode;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    @Override
-    public String toString() {
-        return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", node=" + getNodeData() + "]";
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2936 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import static com.oracle.truffle.dsl.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.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.ArrayCodeTypeMirror;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality;
-import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> {
-
-    private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode";
-
-    private static final String EXECUTE_CHAINED = "executeChained0";
-    private static final String SPECIALIZE = "specialize0";
-    private static final String DSLSHARE_REWRITE = "rewrite";
-    private static final String DSLSHARE_FIND_ROOT = "findRoot";
-    private static final String DSLSHARE_REWRITE_TO_POLYMORHPIC = "rewriteToPolymorphic";
-    private static final String EXECUTE_UNINITIALIZED = "executeUninitialized0";
-    private static final String REWRITE = "rewrite0";
-    private static final String CREATE_INFO = "createInfo0";
-    private static final String CONTAINS_FALLBACK = "containsFallback";
-
-    private static final String FACTORY_METHOD_NAME = "create0";
-    private static final String EMPTY_CLASS_ARRAY = "EMPTY_CLASS_ARRAY";
-
-    private static final String METADATA_FIELD_NAME = "METADATA";
-
-    private TypeMirror getUnexpectedValueException() {
-        return getContext().getTruffleTypes().getUnexpectedValueException();
-    }
-
-    private static String factoryClassName(NodeData node) {
-        return node.getNodeId() + "Factory";
-    }
-
-    private static String nodeSpecializationClassName(SpecializationData specialization) {
-        String nodeid = resolveNodeId(specialization.getNode());
-        String name = Utils.firstLetterUpperCase(nodeid);
-        name += Utils.firstLetterUpperCase(specialization.getId());
-        name += "Node";
-        return name;
-    }
-
-    private static String nodePolymorphicClassName(NodeData node) {
-        return Utils.firstLetterUpperCase(resolveNodeId(node)) + "PolymorphicNode";
-    }
-
-    private static String resolveNodeId(NodeData node) {
-        String nodeid = node.getNodeId();
-        if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
-            nodeid = nodeid.substring(0, nodeid.length() - 4);
-        }
-        return nodeid;
-    }
-
-    private static String valueNameEvaluated(ActualParameter targetParameter) {
-        return valueName(targetParameter) + "Evaluated";
-    }
-
-    private static String implicitTypeName(ActualParameter param) {
-        return param.getLocalName() + "ImplicitType";
-    }
-
-    private static String polymorphicTypeName(NodeExecutionData param) {
-        return param.getName() + "PolymorphicType";
-    }
-
-    private static String valueName(ActualParameter param) {
-        return param.getLocalName();
-    }
-
-    private static CodeTree createAccessChild(NodeExecutionData targetExecution, String thisReference) {
-        String reference = thisReference;
-        if (reference == null) {
-            reference = "this";
-        }
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        Element accessElement = targetExecution.getChild().getAccessElement();
-        if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) {
-            builder.string(reference).string(".").string(targetExecution.getChild().getName());
-        } else if (accessElement.getKind() == ElementKind.FIELD) {
-            builder.string(reference).string(".").string(accessElement.getSimpleName().toString());
-        } else {
-            throw new AssertionError();
-        }
-        if (targetExecution.isIndexed()) {
-            builder.string("[" + targetExecution.getIndex() + "]");
-        }
-        return builder.getRoot();
-    }
-
-    private static String castValueName(ActualParameter parameter) {
-        return valueName(parameter) + "Cast";
-    }
-
-    private void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean evaluated) {
-        if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
-            method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
-        }
-        for (ActualParameter parameter : specialization.getParameters()) {
-            ParameterSpec spec = parameter.getSpecification();
-            if (forceFrame && spec.getName().equals("frame")) {
-                continue;
-            }
-            if (spec.isLocal()) {
-                continue;
-            }
-
-            String name = valueName(parameter);
-            if (evaluated && spec.isSignature()) {
-                name = valueNameEvaluated(parameter);
-            }
-
-            method.addParameter(new CodeVariableElement(parameter.getType(), name));
-        }
-    }
-
-    private static void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame,
-                    Map<String, String> customNames) {
-        if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
-            builder.string("frameValue");
-        }
-        for (ActualParameter parameter : specialization.getParameters()) {
-            ParameterSpec spec = parameter.getSpecification();
-            if (forceFrame && spec.getName().equals("frame")) {
-                continue;
-            }
-
-            if (parameter.getSpecification().isLocal()) {
-                continue;
-            }
-
-            ActualParameter sourceParameter = source.findParameter(parameter.getLocalName());
-
-            if (customNames != null && customNames.containsKey(parameter.getLocalName())) {
-                builder.string(customNames.get(parameter.getLocalName()));
-            } else if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) {
-                builder.cast(parameter.getType(), CodeTreeBuilder.singleString("ex.getResult()"));
-            } else if (sourceParameter != null) {
-                builder.string(valueName(sourceParameter, parameter));
-            } else {
-                builder.string(valueName(parameter));
-            }
-        }
-    }
-
-    private static String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) {
-        if (!sourceParameter.getSpecification().isSignature()) {
-            return valueName(targetParameter);
-        } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) {
-            if (sourceParameter.getTypeSystemType().needsCastTo(targetParameter.getTypeSystemType())) {
-                return castValueName(targetParameter);
-            }
-        }
-        return valueName(targetParameter);
-    }
-
-    private static CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName,
-                    String... customSignatureValueNames) {
-        CodeTreeBuilder builder = parent.create();
-
-        boolean castedValues = sourceMethod != targetMethod;
-
-        builder.startGroup();
-        ExecutableElement method = targetMethod.getMethod();
-        if (method == null) {
-            throw new UnsupportedOperationException();
-        }
-        TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement());
-        NodeData node = (NodeData) targetMethod.getTemplate();
-
-        if (target == null) {
-            boolean accessible = targetMethod.canBeAccessedByInstanceOf(node.getNodeType());
-            if (accessible) {
-                if (builder.findMethod().getModifiers().contains(STATIC)) {
-                    if (method.getModifiers().contains(STATIC)) {
-                        builder.type(targetClass.asType());
-                    } else {
-                        builder.string(THIS_NODE_LOCAL_VAR_NAME);
-                    }
-                } else {
-                    if (targetMethod instanceof ExecutableTypeData) {
-                        builder.string("this");
-                    } else {
-                        builder.string("super");
-                    }
-                }
-            } else {
-                if (method.getModifiers().contains(STATIC)) {
-                    builder.type(targetClass.asType());
-                } else {
-                    ActualParameter firstParameter = null;
-                    for (ActualParameter searchParameter : targetMethod.getParameters()) {
-                        if (searchParameter.getSpecification().isSignature()) {
-                            firstParameter = searchParameter;
-                            break;
-                        }
-                    }
-                    if (firstParameter == null) {
-                        throw new AssertionError();
-                    }
-
-                    ActualParameter sourceParameter = sourceMethod.findParameter(firstParameter.getLocalName());
-
-                    if (castedValues && sourceParameter != null) {
-                        builder.string(valueName(sourceParameter, firstParameter));
-                    } else {
-                        builder.string(valueName(firstParameter));
-                    }
-                }
-            }
-            builder.string(".");
-        } else {
-            builder.tree(target);
-        }
-        builder.startCall(method.getSimpleName().toString());
-
-        int signatureIndex = 0;
-
-        for (ActualParameter targetParameter : targetMethod.getParameters()) {
-            ActualParameter valueParameter = null;
-            if (sourceMethod != null) {
-                valueParameter = sourceMethod.findParameter(targetParameter.getLocalName());
-            }
-            if (valueParameter == null) {
-                valueParameter = targetParameter;
-            }
-            TypeMirror targetType = targetParameter.getType();
-            TypeMirror valueType = null;
-            if (valueParameter != null) {
-                valueType = valueParameter.getType();
-            }
-
-            if (signatureIndex < customSignatureValueNames.length && targetParameter.getSpecification().isSignature()) {
-                builder.string(customSignatureValueNames[signatureIndex]);
-                signatureIndex++;
-            } else if (targetParameter.getSpecification().isLocal()) {
-                builder.startGroup();
-                if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) {
-                    builder.string(THIS_NODE_LOCAL_VAR_NAME).string(".");
-                } else {
-                    builder.string("this.");
-                }
-                builder.string(targetParameter.getSpecification().getName());
-                builder.end();
-            } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) {
-                builder.cast(targetParameter.getType(), CodeTreeBuilder.singleString("ex.getResult()"));
-            } else if (!Utils.needsCastTo(valueType, targetType)) {
-                builder.startGroup();
-                builder.string(valueName(targetParameter));
-                builder.end();
-            } else {
-                builder.string(castValueName(targetParameter));
-            }
-        }
-
-        builder.end().end();
-
-        return builder.getRoot();
-    }
-
-    private static String baseClassName(NodeData node) {
-        String nodeid = resolveNodeId(node);
-        String name = Utils.firstLetterUpperCase(nodeid);
-        name += "BaseNode";
-        return name;
-    }
-
-    private static CodeTree createCallTypeSystemMethod(CodeTreeBuilder parent, NodeData node, String methodName, CodeTree... args) {
-        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-        startCallTypeSystemMethod(builder, node.getTypeSystem(), methodName);
-        for (CodeTree arg : args) {
-            builder.tree(arg);
-        }
-        builder.end().end();
-        return builder.getRoot();
-    }
-
-    private static void startCallTypeSystemMethod(CodeTreeBuilder body, TypeSystemData typeSystem, String methodName) {
-        GeneratedTypeMirror typeMirror = new GeneratedTypeMirror(Utils.getPackageName(typeSystem.getTemplateType()), TypeSystemCodeGenerator.typeName(typeSystem));
-        body.startGroup();
-        body.staticReference(typeMirror, TypeSystemCodeGenerator.singletonName(typeSystem));
-        body.string(".").startCall(methodName);
-    }
-
-    /**
-     * <pre>
-     * variant1 $condition != null
-     *
-     * $type $name = defaultValue($type);
-     * if ($condition) {
-     *     $name = $value;
-     * }
-     *
-     * variant2 $condition != null
-     * $type $name = $value;
-     * </pre>
-     *
-     * .
-     */
-    private static CodeTree createLazyAssignment(CodeTreeBuilder parent, String name, TypeMirror type, CodeTree condition, CodeTree value) {
-        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-        if (condition == null) {
-            builder.declaration(type, name, value);
-        } else {
-            builder.declaration(type, name, new CodeTreeBuilder(parent).defaultValue(type).getRoot());
-
-            builder.startIf().tree(condition).end();
-            builder.startBlock();
-            builder.startStatement();
-            builder.string(name);
-            builder.string(" = ");
-            builder.tree(value);
-            builder.end(); // statement
-            builder.end(); // block
-        }
-        return builder.getRoot();
-    }
-
-    protected void emitEncounteredSynthetic(CodeTreeBuilder builder, TemplateMethod current) {
-        CodeTreeBuilder nodes = builder.create();
-        CodeTreeBuilder arguments = builder.create();
-        nodes.startCommaGroup();
-        arguments.startCommaGroup();
-        boolean empty = true;
-        for (ActualParameter parameter : current.getParameters()) {
-            NodeExecutionData executionData = parameter.getSpecification().getExecution();
-            if (executionData != null) {
-                if (executionData.isShortCircuit()) {
-                    nodes.nullLiteral();
-                    arguments.string(valueName(parameter.getPreviousParameter()));
-                }
-                nodes.tree(createAccessChild(executionData, "rootNode"));
-                arguments.string(valueName(parameter));
-                empty = false;
-            }
-        }
-        nodes.end();
-        arguments.end();
-        builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end();
-
-        builder.declaration(baseClassName(getModel()), "rootNode", builder.create().startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_FIND_ROOT).string("this").end());
-        builder.startThrow().startNew(getContext().getType(UnsupportedSpecializationException.class));
-        builder.string("rootNode");
-        builder.startNewArray(getContext().getTruffleTypes().getNodeArray(), null);
-        builder.tree(nodes.getRoot());
-        builder.end();
-        if (!empty) {
-            builder.tree(arguments.getRoot());
-        }
-        builder.end().end();
-    }
-
-    private static List<ExecutableElement> findUserConstructors(TypeMirror nodeType) {
-        List<ExecutableElement> constructors = new ArrayList<>();
-        for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(nodeType).getEnclosedElements())) {
-            if (constructor.getModifiers().contains(PRIVATE)) {
-                continue;
-            }
-            if (isCopyConstructor(constructor)) {
-                continue;
-            }
-            constructors.add(constructor);
-        }
-
-        if (constructors.isEmpty()) {
-            constructors.add(new CodeExecutableElement(null, Utils.getSimpleName(nodeType)));
-        }
-
-        return constructors;
-    }
-
-    private static ExecutableElement findCopyConstructor(TypeMirror type) {
-        for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(type).getEnclosedElements())) {
-            if (constructor.getModifiers().contains(PRIVATE)) {
-                continue;
-            }
-            if (isCopyConstructor(constructor)) {
-                return constructor;
-            }
-        }
-
-        return null;
-    }
-
-    private static boolean isCopyConstructor(ExecutableElement element) {
-        if (element.getParameters().size() != 1) {
-            return false;
-        }
-        VariableElement var = element.getParameters().get(0);
-        TypeElement enclosingType = Utils.findNearestEnclosingType(var);
-        if (Utils.typeEquals(var.asType(), enclosingType.asType())) {
-            return true;
-        }
-        List<TypeElement> types = Utils.getDirectSuperTypes(enclosingType);
-        for (TypeElement type : types) {
-            if (!(type instanceof CodeTypeElement)) {
-                // no copy constructors which are not generated types
-                return false;
-            }
-
-            if (Utils.typeEquals(var.asType(), type.asType())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    protected void createChildren(NodeData node) {
-        List<CodeTypeElement> casts = new ArrayList<>(getElement().getEnclosedElements());
-        getElement().getEnclosedElements().clear();
-
-        Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>();
-        for (NodeData nodeChild : node.getEnclosingNodes()) {
-            NodeCodeGenerator generator = new NodeCodeGenerator();
-            childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements());
-        }
-
-        if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) {
-            NodeFactoryFactory factory = new NodeFactoryFactory(childTypes);
-            add(factory, node);
-            factory.getElement().getEnclosedElements().addAll(casts);
-        }
-    }
-
-    private static CodeTree createCastType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) {
-        if (targetType == null) {
-            return value;
-        } else if (sourceType != null && !sourceType.needsCastTo(targetType)) {
-            return value;
-        }
-
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        String targetMethodName;
-        if (expect) {
-            targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType);
-        } else {
-            targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
-        }
-        startCallTypeSystemMethod(builder, typeSystem, targetMethodName);
-        builder.tree(value);
-        builder.end().end();
-        return builder.getRoot();
-    }
-
-    private static CodeTree createExpectType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, CodeTree expression) {
-        return createCastType(typeSystem, sourceType, targetType, true, expression);
-    }
-
-    private CodeTree createDeoptimize(CodeTreeBuilder parent) {
-        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-        builder.startStatement();
-        builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end();
-        builder.end();
-        return builder.getRoot();
-    }
-
-    private class NodeFactoryFactory extends ClassElementFactory<NodeData> {
-
-        private final Map<NodeData, List<TypeElement>> childTypes;
-        private CodeTypeElement generatedNode;
-
-        public NodeFactoryFactory(Map<NodeData, List<TypeElement>> childElements) {
-            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);
-            return clazz;
-        }
-
-        @Override
-        protected void createChildren(NodeData node) {
-            CodeTypeElement clazz = getElement();
-
-            Modifier createVisibility = Utils.getVisibility(clazz.getModifiers());
-
-            if (node.needsFactory()) {
-                NodeBaseFactory factory = new NodeBaseFactory();
-                add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization());
-                generatedNode = factory.getElement();
-
-                createFactoryMethods(node, clazz, createVisibility);
-
-                for (SpecializationData specialization : node.getSpecializations()) {
-                    if (!specialization.isReachable() || specialization.isGeneric()) {
-                        continue;
-                    }
-
-                    if (specialization.isPolymorphic() && node.isPolymorphic(context)) {
-                        PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(generatedNode);
-                        add(polymorphicFactory, specialization);
-                        continue;
-                    }
-
-                    add(new SpecializedNodeFactory(generatedNode), specialization);
-                }
-
-                TypeMirror nodeFactory = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getTruffleTypes().getNodeFactoryBase()), node.getNodeType());
-                clazz.setSuperClass(nodeFactory);
-                clazz.add(createNodeFactoryConstructor(node));
-                clazz.add(createCreateNodeMethod(node));
-// clazz.add(createGetNodeClassMethod(node));
-// clazz.add(createGetNodeSignaturesMethod());
-// clazz.add(createGetChildrenSignatureMethod(node));
-                clazz.add(createGetInstanceMethod(node, createVisibility));
-                clazz.add(createInstanceConstant(node, clazz.asType()));
-            }
-
-            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);
-                }
-            }
-
-            List<NodeData> children = node.getNodeDeclaringChildren();
-            if (node.getDeclaringNode() == null && children.size() > 0) {
-                clazz.add(createGetFactories(node));
-            }
-
-        }
-
-        private Element createNodeFactoryConstructor(NodeData node) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), null, factoryClassName(node));
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.startStatement();
-            builder.startCall("super");
-
-            // node type
-            builder.typeLiteral(node.getNodeType());
-
-            // execution signature
-            builder.startGroup();
-            if (node.getChildExecutions().isEmpty()) {
-                builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
-            } else {
-                builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null);
-                for (NodeExecutionData execution : node.getChildExecutions()) {
-                    builder.typeLiteral(execution.getNodeType());
-                }
-                builder.end();
-            }
-            builder.end();
-
-            // node signatures
-            builder.startGroup();
-            builder.startNewArray(new ArrayCodeTypeMirror(new ArrayCodeTypeMirror(context.getType(Class.class))), null);
-            List<ExecutableElement> constructors = findUserConstructors(generatedNode.asType());
-            for (ExecutableElement constructor : constructors) {
-                builder.startGroup();
-                if (constructor.getParameters().isEmpty()) {
-                    builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
-                } else {
-                    builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null);
-                    for (VariableElement var : constructor.getParameters()) {
-                        builder.typeLiteral(var.asType());
-                    }
-                    builder.end();
-                }
-                builder.end();
-            }
-            builder.end();
-            builder.end();
-
-            builder.end().end().end();
-            return method;
-        }
-
-        private CodeExecutableElement createCreateNodeMethod(NodeData node) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode");
-            CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments");
-            method.setVarArgs(true);
-            method.addParameter(arguments);
-
-            CodeTreeBuilder builder = method.createBuilder();
-            List<ExecutableElement> signatures = findUserConstructors(generatedNode.asType());
-            boolean ifStarted = false;
-
-            for (ExecutableElement element : signatures) {
-                ifStarted = builder.startIf(ifStarted);
-                builder.string("arguments.length == " + element.getParameters().size());
-
-                int index = 0;
-                for (VariableElement param : element.getParameters()) {
-                    if (Utils.isObject(param.asType())) {
-                        continue;
-                    }
-                    builder.string(" && ");
-                    if (!param.asType().getKind().isPrimitive()) {
-                        builder.string("(arguments[" + index + "] == null || ");
-                    }
-                    builder.string("arguments[" + index + "] instanceof ");
-                    builder.type(Utils.boxType(getContext(), param.asType()));
-                    if (!param.asType().getKind().isPrimitive()) {
-                        builder.string(")");
-                    }
-                    index++;
-                }
-                builder.end();
-                builder.startBlock();
-
-                builder.startReturn().startCall("create");
-                index = 0;
-                for (VariableElement param : element.getParameters()) {
-                    builder.startGroup();
-                    if (!Utils.isObject(param.asType())) {
-                        builder.string("(").type(param.asType()).string(") ");
-                    }
-                    builder.string("arguments[").string(String.valueOf(index)).string("]");
-                    builder.end();
-                    index++;
-                }
-                builder.end().end();
-
-                builder.end(); // block
-            }
-
-            builder.startElseBlock();
-            builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class));
-            builder.doubleQuote("Invalid create signature.");
-            builder.end().end();
-            builder.end(); // else block
-            return method;
-        }
-
-        private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) {
-            TypeElement nodeFactoryType = Utils.fromTypeMirror(getContext().getType(NodeFactory.class));
-            TypeMirror returnType = Utils.getDeclaredType(nodeFactoryType, node.getNodeType());
-
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance");
-            if (visibility != null) {
-                method.getModifiers().add(visibility);
-            }
-            method.getModifiers().add(Modifier.STATIC);
-
-            String varName = instanceVarName(node);
-
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.startIf();
-            builder.string(varName).string(" == null");
-            builder.end().startBlock();
-
-            builder.startStatement();
-            builder.string(varName);
-            builder.string(" = ");
-            builder.startNew(factoryClassName(node)).end();
-            builder.end();
-
-            builder.end();
-            builder.startReturn().string(varName).end();
-            return method;
-        }
-
-        private String instanceVarName(NodeData node) {
-            if (node.getDeclaringNode() != null) {
-                return Utils.firstLetterLowerCase(factoryClassName(node)) + "Instance";
-            } else {
-                return "instance";
-            }
-        }
-
-        private CodeVariableElement createInstanceConstant(NodeData node, TypeMirror factoryType) {
-            String varName = instanceVarName(node);
-            CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName);
-            var.getModifiers().add(Modifier.PRIVATE);
-            var.getModifiers().add(Modifier.STATIC);
-            return var;
-        }
-
-        private ExecutableElement createGetFactories(NodeData node) {
-            List<NodeData> children = node.getNodeDeclaringChildren();
-            if (node.needsFactory()) {
-                children.add(node);
-            }
-
-            List<TypeMirror> nodeTypesList = new ArrayList<>();
-            TypeMirror prev = null;
-            boolean allSame = true;
-            for (NodeData child : children) {
-                nodeTypesList.add(child.getNodeType());
-                if (prev != null && !Utils.typeEquals(child.getNodeType(), prev)) {
-                    allSame = false;
-                }
-                prev = child.getNodeType();
-            }
-            TypeMirror commonNodeSuperType = Utils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()]));
-
-            Types types = getContext().getEnvironment().getTypeUtils();
-            TypeMirror factoryType = getContext().getType(NodeFactory.class);
-            TypeMirror baseType;
-            if (allSame) {
-                baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType);
-            } else {
-                baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null));
-            }
-            TypeMirror listType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType);
-
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories");
-
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.startReturn();
-            builder.startStaticCall(getContext().getType(Arrays.class), "asList");
-
-            for (NodeData child : children) {
-                builder.startGroup();
-                NodeData childNode = child;
-                List<NodeData> factories = new ArrayList<>();
-                while (childNode.getDeclaringNode() != null) {
-                    factories.add(childNode);
-                    childNode = childNode.getDeclaringNode();
-                }
-                Collections.reverse(factories);
-                for (NodeData nodeData : factories) {
-                    builder.string(factoryClassName(nodeData)).string(".");
-                }
-                builder.string("getInstance()");
-                builder.end();
-            }
-            builder.end();
-            builder.end();
-            return method;
-        }
-
-        private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) {
-            List<ExecutableElement> constructors = findUserConstructors(generatedNode.asType());
-            for (ExecutableElement constructor : constructors) {
-                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().isEmpty()) {
-                body.nullLiteral();
-            } else {
-                body.startCall(nodeSpecializationClassName(node.getSpecializations().get(0)), FACTORY_METHOD_NAME);
-                for (VariableElement var : method.getParameters()) {
-                    body.string(var.getSimpleName().toString());
-                }
-                body.end();
-            }
-            body.end();
-            return method;
-        }
-
-    }
-
-    private class NodeBaseFactory extends ClassElementFactory<SpecializationData> {
-
-        @Override
-        protected CodeTypeElement create(SpecializationData specialization) {
-            NodeData node = specialization.getNode();
-            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false);
-            clazz.getImplements().add(context.getTruffleTypes().getDslNode());
-
-            for (NodeChildData child : node.getChildren()) {
-                clazz.add(createChildField(child));
-
-                if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) {
-                    ExecutableElement getter = (ExecutableElement) child.getAccessElement();
-                    CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter);
-                    method.getModifiers().remove(Modifier.ABSTRACT);
-                    CodeTreeBuilder builder = method.createBuilder();
-                    builder.startReturn().string("this.").string(child.getName()).end();
-                    clazz.add(method);
-                }
-            }
-
-            for (NodeFieldData field : node.getFields()) {
-                if (!field.isGenerated()) {
-                    continue;
-                }
-
-                clazz.add(new CodeVariableElement(modifiers(PROTECTED, FINAL), field.getType(), field.getName()));
-                if (field.getGetter() != null && field.getGetter().getModifiers().contains(Modifier.ABSTRACT)) {
-                    CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), field.getGetter());
-                    method.getModifiers().remove(Modifier.ABSTRACT);
-                    method.createBuilder().startReturn().string("this.").string(field.getName()).end();
-                    clazz.add(method);
-                }
-            }
-
-            for (String assumption : node.getAssumptions()) {
-                clazz.add(createAssumptionField(assumption));
-            }
-
-            createConstructors(node, clazz);
-
-            return clazz;
-        }
-
-        @Override
-        protected void createChildren(SpecializationData specialization) {
-            NodeData node = specialization.getNode();
-            CodeTypeElement clazz = getElement();
-
-            SpecializationGroup rootGroup = createSpecializationGroups(node);
-
-            if (node.needsRewrites(context)) {
-                if (node.isPolymorphic(context)) {
-
-                    CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0");
-                    var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation()));
-                    clazz.add(var);
-
-                    CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization());
-                    clazz.add(genericCachedExecute);
-
-                }
-
-                for (CodeExecutableElement method : createImplicitChildrenAccessors()) {
-                    clazz.add(method);
-                }
-                clazz.add(createInfoMessage(node));
-                clazz.add(createMonomorphicRewrite());
-                clazz.add(createCreateSpecializationMethod(node, rootGroup));
-            }
-
-            clazz.add(createAdoptChildren0());
-            clazz.add(createGetMetadata0(true));
-            clazz.add(createUpdateTypes0());
-            clazz.add(createGetNext());
-        }
-
-        private Element createGetNext() {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(Node.class), "getNext0");
-            CodeTreeBuilder builder = method.createBuilder();
-            NodeData node = getModel().getNode();
-
-            if (node.isPolymorphic(context)) {
-                builder.startReturn().string("next0").end();
-            } else {
-                builder.returnNull();
-            }
-
-            return method;
-        }
-
-        protected final CodeExecutableElement createUpdateTypes0() {
-            ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class));
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(void.class), "updateTypes0");
-            method.getParameters().add(new CodeVariableElement(classArray, "types"));
-
-            if (getModel().isPolymorphic()) {
-                CodeTreeBuilder builder = method.createBuilder();
-
-                int index = 0;
-                for (NodeExecutionData execution : getModel().getNode().getChildExecutions()) {
-                    String fieldName = polymorphicTypeName(execution);
-
-                    builder.startStatement();
-                    builder.string(fieldName).string(" = ").string("types[").string(String.valueOf(index)).string("]");
-                    builder.end();
-                    index++;
-                }
-            }
-
-            return method;
-        }
-
-        protected final CodeExecutableElement createGetMetadata0(boolean empty) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getTruffleTypes().getDslMetadata(), "getMetadata0");
-            if (empty) {
-                method.createBuilder().startReturn().staticReference(context.getTruffleTypes().getDslMetadata(), "NONE").end();
-            } else {
-                method.createBuilder().startReturn().string(METADATA_FIELD_NAME).end();
-            }
-            return method;
-        }
-
-        private CodeExecutableElement createAdoptChildren0() {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(void.class), "adoptChildren0");
-            method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "other"));
-            method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "newNext"));
-            NodeData node = getModel().getNode();
-            CodeTreeBuilder builder = method.createBuilder();
-            List<NodeExecutionData> executions = node.getChildExecutions();
-
-            if (executions.size() > 0) {
-                builder.startIf().string("other == null").end().startBlock();
-                for (NodeExecutionData execution : executions) {
-                    builder.startStatement().tree(createAccessChild(execution, "this")).string(" = null").end();
-                }
-                builder.end().startElseBlock();
-
-                String access;
-                if (executions.size() > 1) {
-                    builder.declaration(baseClassName(node), "otherCast", builder.create().cast(baseClassName(node)).string("other"));
-                    access = "otherCast";
-                } else {
-                    assert executions.size() == 1;
-                    access = "((" + baseClassName(node) + ") other)";
-                }
-                for (NodeExecutionData execution : executions) {
-                    builder.startStatement().tree(createAccessChild(execution, "this")).string(" = ").tree(createAccessChild(execution, access)).end();
-                }
-
-                builder.end();
-            }
-
-            if (getModel().getNode().isPolymorphic(context)) {
-                builder.startIf().string("newNext == null").end().startBlock();
-                builder.statement("this.next0 = null");
-                builder.end().startElseBlock();
-                builder.statement("this.next0 = (" + baseClassName(getModel().getNode()) + ") newNext");
-                builder.end();
-            }
-
-            return method;
-        }
-
-        private List<CodeExecutableElement> createImplicitChildrenAccessors() {
-            NodeData node = getModel().getNode();
-            List<Set<TypeData>> prototype = Collections.nCopies(node.getGenericSpecialization().getParameters().size(), null);
-            List<Set<TypeData>> expectTypes = new ArrayList<>(prototype);
-
-            for (ExecutableTypeData executableType : node.getExecutableTypes()) {
-                for (int i = 0; i < executableType.getEvaluatedCount(); i++) {
-                    ActualParameter parameter = executableType.getSignatureParameter(i);
-                    if (i >= expectTypes.size()) {
-                        break;
-                    }
-                    Set<TypeData> types = expectTypes.get(i);
-                    if (types == null) {
-                        types = new TreeSet<>();
-                        expectTypes.set(i, types);
-                    }
-                    types.add(parameter.getTypeSystemType());
-                }
-            }
-
-            List<CodeExecutableElement> methods = new ArrayList<>();
-            List<Set<TypeData>> visitedList = new ArrayList<>(prototype);
-            for (SpecializationData spec : node.getSpecializations()) {
-                int signatureIndex = -1;
-                for (ActualParameter param : spec.getParameters()) {
-                    if (!param.getSpecification().isSignature()) {
-                        continue;
-                    }
-                    signatureIndex++;
-                    Set<TypeData> visitedTypeData = visitedList.get(signatureIndex);
-                    if (visitedTypeData == null) {
-                        visitedTypeData = new TreeSet<>();
-                        visitedList.set(signatureIndex, visitedTypeData);
-                    }
-
-                    if (visitedTypeData.contains(param.getTypeSystemType())) {
-                        continue;
-                    }
-                    visitedTypeData.add(param.getTypeSystemType());
-
-                    Set<TypeData> expect = expectTypes.get(signatureIndex);
-                    if (expect == null) {
-                        expect = Collections.emptySet();
-                    }
-
-                    methods.addAll(createExecuteChilds(param, expect));
-                }
-            }
-            return methods;
-        }
-
-        private CodeTree truffleBooleanOption(CodeTreeBuilder parent, String name) {
-            CodeTreeBuilder builder = parent.create();
-            builder.staticReference(getContext().getTruffleTypes().getTruffleOptions(), name);
-            return builder.getRoot();
-        }
-
-        private Element createInfoMessage(NodeData node) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), getContext().getType(String.class), CREATE_INFO);
-            method.addParameter(new CodeVariableElement(getContext().getType(String.class), "message"));
-            addInternalValueParameters(method, node.getGenericSpecialization(), false, false);
-
-            CodeTreeBuilder builder = method.createBuilder();
-
-            builder.startIf().tree(truffleBooleanOption(builder, TruffleTypes.OPTION_DETAILED_REWRITE_REASONS)).end();
-            builder.startBlock();
-
-            builder.startStatement().string("StringBuilder builder = new StringBuilder(message)").end();
-            builder.startStatement().startCall("builder", "append").doubleQuote(" (").end().end();
-
-            String sep = null;
-            for (ActualParameter parameter : node.getGenericSpecialization().getSignatureParameters()) {
-                builder.startStatement();
-                builder.string("builder");
-                if (sep != null) {
-                    builder.startCall(".append").doubleQuote(sep).end();
-                }
-                builder.startCall(".append").doubleQuote(parameter.getLocalName()).end();
-                builder.startCall(".append").doubleQuote(" = ").end();
-                builder.startCall(".append").string(parameter.getLocalName()).end();
-                builder.end();
-
-                if (!Utils.isPrimitive(parameter.getType())) {
-                    builder.startIf().string(parameter.getLocalName() + " != null").end();
-                    builder.startBlock();
-                }
-                builder.startStatement();
-                if (Utils.isPrimitive(parameter.getType())) {
-                    builder.startCall("builder.append").doubleQuote(" (" + Utils.getSimpleName(parameter.getType()) + ")").end();
-                } else {
-                    builder.startCall("builder.append").doubleQuote(" (").end();
-                    builder.startCall(".append").string(parameter.getLocalName() + ".getClass().getSimpleName()").end();
-                    builder.startCall(".append").doubleQuote(")").end();
-                }
-                builder.end();
-                if (!Utils.isPrimitive(parameter.getType())) {
-                    builder.end();
-                }
-
-                sep = ", ";
-            }
-
-            builder.startStatement().startCall("builder", "append").doubleQuote(")").end().end();
-            builder.startReturn().string("builder.toString()").end();
-
-            builder.end();
-            builder.startElseBlock();
-            builder.startReturn().string("message").end();
-            builder.end();
-
-            return method;
-        }
-
-        private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) {
-            CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_CHAINED);
-            addInternalValueParameters(cachedExecute, polymorph, true, false);
-
-            ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0);
-            boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext());
-            if (sourceThrowsUnexpected && sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) {
-                sourceThrowsUnexpected = false;
-            }
-            if (sourceThrowsUnexpected) {
-                cachedExecute.getThrownTypes().add(getContext().getType(UnexpectedResultException.class));
-            }
-            return cachedExecute;
-
-        }
-
-        private void createConstructors(NodeData node, CodeTypeElement clazz) {
-            List<ExecutableElement> constructors = findUserConstructors(node.getNodeType());
-            ExecutableElement sourceSectionConstructor = null;
-            if (constructors.isEmpty()) {
-                clazz.add(createUserConstructor(clazz, null));
-            } else {
-                for (ExecutableElement constructor : constructors) {
-                    clazz.add(createUserConstructor(clazz, constructor));
-                    if (NodeParser.isSourceSectionConstructor(context, constructor)) {
-                        sourceSectionConstructor = constructor;
-                    }
-                }
-            }
-            if (node.needsRewrites(getContext())) {
-                ExecutableElement copyConstructor = findCopyConstructor(node.getNodeType());
-                clazz.add(createCopyConstructor(clazz, copyConstructor, sourceSectionConstructor));
-            }
-        }
-
-        private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
-            CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
-            CodeTreeBuilder builder = method.createBuilder();
-
-            NodeData node = getModel().getNode();
-
-            if (superConstructor != null) {
-                for (VariableElement param : superConstructor.getParameters()) {
-                    method.getParameters().add(CodeVariableElement.clone(param));
-                }
-            }
-
-            if (superConstructor != null) {
-                builder.startStatement().startSuperCall();
-                for (VariableElement param : superConstructor.getParameters()) {
-                    builder.string(param.getSimpleName().toString());
-                }
-                builder.end().end();
-            }
-
-            for (VariableElement var : type.getFields()) {
-                if (var.getModifiers().contains(STATIC)) {
-                    continue;
-                }
-                NodeChildData child = node.findChild(var.getSimpleName().toString());
-
-                if (child != null) {
-                    method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName()));
-                } else {
-                    method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
-                }
-
-                builder.startStatement();
-                String fieldName = var.getSimpleName().toString();
-
-                CodeTree init = createStaticCast(builder, child, fieldName);
-
-                builder.string("this.").string(fieldName).string(" = ").tree(init);
-                builder.end();
-            }
-            return method;
-        }
-
-        private CodeTree createStaticCast(CodeTreeBuilder parent, NodeChildData child, String fieldName) {
-            NodeData parentNode = getModel().getNode();
-            if (child != null) {
-                CreateCastData createCast = parentNode.findCast(child.getName());
-                if (createCast != null) {
-                    return createTemplateMethodCall(parent, null, parentNode.getGenericSpecialization(), createCast, null, fieldName);
-                }
-            }
-            return CodeTreeBuilder.singleString(fieldName);
-        }
-
-        private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor, ExecutableElement sourceSectionConstructor) {
-            CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
-            CodeTreeBuilder builder = method.createBuilder();
-            method.getParameters().add(new CodeVariableElement(type.asType(), "copy"));
-
-            if (superConstructor != null) {
-                builder.startStatement().startSuperCall().string("copy").end().end();
-            } else if (sourceSectionConstructor != null) {
-                builder.startStatement().startSuperCall().string("copy.getSourceSection()").end().end();
-            }
-
-            for (VariableElement var : type.getFields()) {
-                if (var.getModifiers().contains(STATIC) || !var.getModifiers().contains(FINAL)) {
-                    continue;
-                }
-                final String varName = var.getSimpleName().toString();
-                final TypeMirror varType = var.asType();
-                if (Utils.isAssignable(varType, getContext().getTruffleTypes().getNodeArray())) {
-                    CodeTree size = builder.create().string("copy.", varName, ".length").getRoot();
-                    builder.startStatement().string("this.").string(varName).string(" = ").startNewArray((ArrayType) varType, size).end().end();
-                } else {
-                    builder.startStatement().string("this.", varName, " = copy.", varName).end();
-                }
-            }
-
-            return method;
-        }
-
-        private CodeVariableElement createAssumptionField(String assumption) {
-            CodeVariableElement var = new CodeVariableElement(getContext().getTruffleTypes().getAssumption(), assumption);
-            var.getModifiers().add(Modifier.FINAL);
-            return var;
-        }
-
-        private CodeVariableElement createChildField(NodeChildData child) {
-            TypeMirror type = child.getNodeType();
-            CodeVariableElement var = new CodeVariableElement(type, child.getName());
-            var.getModifiers().add(Modifier.PROTECTED);
-
-            DeclaredType annotationType;
-            if (child.getCardinality() == Cardinality.MANY) {
-                var.getModifiers().add(Modifier.FINAL);
-                annotationType = getContext().getTruffleTypes().getChildrenAnnotation();
-            } else {
-                annotationType = getContext().getTruffleTypes().getChildAnnotation();
-            }
-
-            var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType));
-            return var;
-        }
-
-        private SpecializationGroup createSpecializationGroups(final NodeData node) {
-            List<SpecializationData> specializations = node.getSpecializations();
-            List<SpecializationData> filteredSpecializations = new ArrayList<>();
-            for (SpecializationData current : specializations) {
-                if (current.isUninitialized() || current.isPolymorphic() || !current.isReachable()) {
-                    continue;
-                }
-                filteredSpecializations.add(current);
-            }
-
-            return SpecializationGroup.create(filteredSpecializations);
-        }
-
-        protected final CodeExecutableElement createExecuteUninitialized() {
-            NodeData node = getModel().getNode();
-            SpecializationData generic = node.getGenericSpecialization();
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), generic.getReturnType().getType(), EXECUTE_UNINITIALIZED);
-            addInternalValueParameters(method, generic, true, false);
-            CodeTreeBuilder builder = method.createBuilder();
-
-            CodeTreeBuilder createSpecializationCall = builder.create();
-            createSpecializationCall.startCall(SPECIALIZE);
-            addInternalValueParameterNames(createSpecializationCall, generic, generic, null, node.needsFrame(getContext()), null);
-            createSpecializationCall.end();
-            builder.declaration(baseClassName(node), "newNode", createSpecializationCall);
-
-            if (generic.isReachable()) {
-                builder.startIf().string("newNode == null").end().startBlock();
-
-                builder.startIf().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "inInterpreter").end().end().startBlock();
-                builder.statement("containsFallback = true");
-                builder.end();
-                builder.tree(createGenericInvoke(builder, generic, generic));
-                builder.end();
-                builder.startElseBlock();
-                builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
-            }
-
-            builder.startReturn();
-            builder.startStaticCall(context.getTruffleTypes().getDslShare(), "rewriteUninitialized").string("this").string("newNode").end();
-            builder.string(".").startCall(EXECUTE_CHAINED);
-            addInternalValueParameterNames(builder, generic, generic, null, true, null);
-            builder.end();
-            builder.end();
-
-            if (generic.isReachable()) {
-                builder.end();
-            }
-
-            return method;
-        }
-
-        private CodeTree createInfoCall(CodeTreeBuilder parent, SpecializationData specialization, String reason) {
-            CodeTreeBuilder builder = parent.create();
-            builder.startCall(CREATE_INFO).string(reason);
-            addInternalValueParameterNames(builder, specialization, specialization, null, false, null);
-            builder.end();
-            return builder.getRoot();
-        }
-
-        private CodeExecutableElement createMonomorphicRewrite() {
-            NodeData node = getModel().getNode();
-
-            SpecializationData generic = node.getGenericSpecialization();
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), generic.getReturnType().getType(), REWRITE);
-            addInternalValueParameters(method, generic, true, false);
-            method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
-
-            CodeTreeBuilder builder = method.createBuilder();
-
-            builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end().end();
-            String baseClassName = baseClassName(getModel().getNode());
-            CodeTreeBuilder createSpecializationCall = builder.create();
-            createSpecializationCall.startCall(SPECIALIZE);
-            addInternalValueParameterNames(createSpecializationCall, generic, generic, null, node.needsFrame(getContext()), null);
-            createSpecializationCall.end();
-            builder.declaration(baseClassName, "newNode", createSpecializationCall);
-
-            builder.startIf().string("newNode == null").end().startBlock();
-            builder.startStatement();
-            String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization());
-            builder.string("newNode = ").startNew(uninitializedName).string("this").end();
-            builder.end();
-            if (node.isFallbackReachable()) {
-                builder.startStatement().string("((", uninitializedName, ") newNode).containsFallback = true").end();
-            }
-            builder.end();
-
-            builder.startStatement();
-            builder.type(getContext().getType(String.class)).string(" message = ").tree(createInfoCall(builder, generic, "reason"));
-            builder.end();
-
-            builder.declaration(baseClassName, "returnNode",
-                            builder.create().startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_REWRITE).string("this").string("newNode").string("message").end().getRoot());
-            builder.startIf().string("returnNode == null").end().startBlock();
-            builder.tree(createRewritePolymorphic(builder, node, "this"));
-            builder.end();
-
-            builder.startReturn();
-            builder.startCall("returnNode", EXECUTE_CHAINED);
-            addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, null);
-            builder.end();
-            builder.end();
-
-            return method;
-        }
-
-        private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node, String currentNode) {
-            String polyClassName = nodePolymorphicClassName(node);
-            CodeTreeBuilder builder = parent.create();
-
-            builder.startStatement().string("returnNode = ");
-            builder.startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_REWRITE_TO_POLYMORHPIC);
-            builder.string("this");
-            builder.tree(builder.create().startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string(currentNode).end().getRoot());
-            builder.tree(builder.create().startNew(polyClassName).string(currentNode).end().getRoot());
-            builder.startGroup().cast(baseClassName(node)).startCall("copy").end().end();
-            builder.string("newNode");
-            builder.string("message");
-            builder.end();
-            builder.end();
-
-            return builder.getRoot();
-        }
-
-        private CodeExecutableElement createCreateSpecializationMethod(NodeData node, SpecializationGroup group) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), new GeneratedTypeMirror(Utils.getPackageName(node.getTemplateType()), baseClassName(node)),
-                            SPECIALIZE);
-            if (!node.needsFrame(getContext())) {
-                method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath()));
-            }
-
-            addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(getContext()), false);
-            final CodeTreeBuilder builder = method.createBuilder();
-            builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, new CodeBlock<SpecializationData>() {
-
-                public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
-                    return createCreateSpecializationMethodBody0(builder, current);
-                }
-            }, null, false, true, false, true));
-
-            emitUnreachableSpecializations(builder, node);
-
-            return method;
-        }
-
-        protected CodeTree createCreateSpecializationMethodBody0(CodeTreeBuilder parent, SpecializationData current) {
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            if (current.isGeneric()) {
-                builder.startReturn().nullLiteral().end();
-            } else {
-                String className = nodeSpecializationClassName(current);
-                if (!current.getExcludedBy().isEmpty()) {
-                    builder.startIf().string("!").startStaticCall(context.getTruffleTypes().getDslShare(), "isExcluded");
-                    builder.string("this").string(nodeSpecializationClassName(current), ".", METADATA_FIELD_NAME).end().end();
-                    builder.startBlock();
-                }
-
-                if (current.getNode().getGenericSpecialization().isReachable()) {
-                    builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
-                }
-                builder.startReturn();
-                builder.cast(baseClassName(getModel().getNode()));
-                builder.startGroup().startCall(className, FACTORY_METHOD_NAME).string("this");
-                for (ActualParameter param : current.getSignatureParameters()) {
-                    NodeChildData child = param.getSpecification().getExecution().getChild();
-                    List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
-                    if (types.size() > 1) {
-                        builder.string(implicitTypeName(param));
-                    }
-                }
-                builder.end().end();
-                builder.end();
-
-                if (!current.getExcludedBy().isEmpty()) {
-                    builder.end();
-                }
-            }
-            return builder.getRoot();
-
-        }
-
-        private void emitUnreachableSpecializations(final CodeTreeBuilder builder, NodeData node) {
-            for (SpecializationData current : node.getSpecializations()) {
-                if (current.isReachable()) {
-                    continue;
-                }
-                builder.string("// unreachable ").string(current.getId()).newLine();
-            }
-        }
-
-        protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final CodeBlock<SpecializationData> guardedblock,
-                        final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions, final boolean typedCasts, final boolean castForGuardsOnly) {
-            return guard(outerParent, source, group, new CodeBlock<Integer>() {
-
-                public CodeTree create(CodeTreeBuilder parent, Integer ifCount) {
-                    CodeTreeBuilder builder = parent.create();
-
-                    if (group.getSpecialization() != null) {
-                        builder.tree(guardedblock.create(builder, group.getSpecialization()));
-
-                        assert group.getChildren().isEmpty() : "missed a specialization";
-
-                    } else {
-                        for (SpecializationGroup childGroup : group.getChildren()) {
-                            builder.tree(createExecuteTree(builder, source, childGroup, guardedblock, null, false, emitAssumptions, typedCasts, castForGuardsOnly));
-                        }
-                    }
-
-                    return builder.getRoot();
-                }
-            }, elseBlock, forceElse, emitAssumptions, typedCasts, castForGuardsOnly);
-        }
-
-        private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, CodeBlock<Integer> bodyBlock, CodeTree elseBlock, boolean forceElse,
-                        boolean emitAssumptions, boolean typedCasts, boolean castForGuardsOnly) {
-            CodeTreeBuilder builder = parent.create();
-
-            int ifCount = emitGuards(builder, source, group, emitAssumptions, typedCasts, castForGuardsOnly);
-
-            if (isReachableGroup(group, ifCount)) {
-                builder.tree(bodyBlock.create(builder, ifCount));
-            }
-
-            builder.end(ifCount);
-
-            if (elseBlock != null) {
-                if (ifCount > 0 || forceElse) {
-                    builder.tree(elseBlock);
-                }
-            }
-
-            return builder.getRoot();
-        }
-
-        private boolean isReachableGroup(SpecializationGroup group, int ifCount) {
-            if (ifCount != 0) {
-                return true;
-            }
-            SpecializationGroup previous = group.getPreviousGroup();
-            if (previous == null || previous.findElseConnectableGuards().isEmpty()) {
-                return true;
-            }
-
-            /*
-             * Hacky else case. In this case the specialization is not reachable due to previous
-             * else branch. This is only true if the minimum state is not checked.
-             */
-            if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && previous.getAssumptions().isEmpty() &&
-                            (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) {
-                return false;
-            }
-
-            return true;
-        }
-
-        private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean emitAssumptions, boolean typedCasts, boolean castForGuardsOnly) {
-            NodeData node = source.getNode();
-
-            CodeTreeBuilder guardsBuilder = builder.create();
-            CodeTreeBuilder castBuilder = builder.create();
-            CodeTreeBuilder guardsCastBuilder = builder.create();
-
-            String guardsAnd = "";
-            String guardsCastAnd = "";
-
-            if (emitAssumptions) {
-                for (String assumption : group.getAssumptions()) {
-                    guardsBuilder.string(guardsAnd);
-                    guardsBuilder.string("this");
-                    guardsBuilder.string(".").string(assumption).string(".isValid()");
-                    guardsAnd = " && ";
-                }
-            }
-
-            for (TypeGuard typeGuard : group.getTypeGuards()) {
-                ActualParameter valueParam = source.getSignatureParameter(typeGuard.getSignatureIndex());
-
-                if (valueParam == null) {
-                    /*
-                     * If used inside a execute evaluated method then the value param may not exist.
-                     * In that case we assume that the value is executed generic or of the current
-                     * specialization.
-                     */
-                    if (group.getSpecialization() != null) {
-                        valueParam = group.getSpecialization().getSignatureParameter(typeGuard.getSignatureIndex());
-                    } else {
-                        valueParam = node.getGenericSpecialization().getSignatureParameter(typeGuard.getSignatureIndex());
-                    }
-                }
-
-                NodeExecutionData execution = valueParam.getSpecification().getExecution();
-                CodeTree implicitGuard = createTypeGuard(guardsBuilder, execution, valueParam, typeGuard.getType(), typedCasts);
-                if (implicitGuard != null) {
-                    guardsBuilder.string(guardsAnd);
-                    guardsBuilder.tree(implicitGuard);
-                    guardsAnd = " && ";
-                }
-
-                CodeTree implicitGetType = null;
-                if (castForGuardsOnly) {
-                    implicitGetType = createGetImplicitType(builder, execution, valueParam, typeGuard.getType());
-                }
-
-                boolean performCast = true;
-                if (castForGuardsOnly) {
-                    // if cast for guards we just cast if the type guard is used inside a guard.
-                    performCast = group.isTypeGuardUsedInAnyGuardBelow(context, source, typeGuard);
-                }
-
-                if (performCast) {
-                    CodeTree cast = createCast(castBuilder, execution, valueParam, typeGuard.getType(), typedCasts);
-                    if (cast != null) {
-                        castBuilder.tree(cast);
-                    }
-                }
-                if (implicitGetType != null) {
-                    castBuilder.tree(implicitGetType);
-                }
-            }
-            List<GuardExpression> elseGuards = group.findElseConnectableGuards();
-
-            for (GuardExpression guard : group.getGuards()) {
-                if (elseGuards.contains(guard)) {
-                    continue;
-                }
-
-                if (needsTypeGuard(source, group, guard)) {
-                    guardsCastBuilder.tree(createMethodGuard(builder, guardsCastAnd, source, guard));
-                    guardsCastAnd = " && ";
-                } else {
-                    guardsBuilder.tree(createMethodGuard(builder, guardsAnd, source, guard));
-                    guardsAnd = " && ";
-                }
-            }
-
-            int ifCount = startGuardIf(builder, guardsBuilder, 0, elseGuards);
-            builder.tree(castBuilder.getRoot());
-            ifCount = startGuardIf(builder, guardsCastBuilder, ifCount, elseGuards);
-            return ifCount;
-        }
-
-        private int startGuardIf(CodeTreeBuilder builder, CodeTreeBuilder conditionBuilder, int ifCount, List<GuardExpression> elseGuard) {
-            int newIfCount = ifCount;
-
-            if (!conditionBuilder.isEmpty()) {
-                if (ifCount == 0 && !elseGuard.isEmpty()) {
-                    builder.startElseIf();
-                } else {
-                    builder.startIf();
-                }
-                builder.tree(conditionBuilder.getRoot());
-                builder.end().startBlock();
-                newIfCount++;
-            } else if (ifCount == 0 && !elseGuard.isEmpty()) {
-                builder.startElseBlock();
-                newIfCount++;
-            }
-            return newIfCount;
-        }
-
-        private boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardExpression guard) {
-            int signatureIndex = 0;
-            for (ActualParameter parameter : guard.getResolvedGuard().getParameters()) {
-                if (!parameter.getSpecification().isSignature()) {
-                    continue;
-                }
-
-                TypeGuard typeGuard = group.findTypeGuard(signatureIndex);
-                if (typeGuard != null) {
-                    TypeData requiredType = typeGuard.getType();
-
-                    ActualParameter sourceParameter = source.findParameter(parameter.getLocalName());
-                    if (sourceParameter == null) {
-                        sourceParameter = source.getNode().getGenericSpecialization().findParameter(parameter.getLocalName());
-                    }
-
-                    if (Utils.needsCastTo(sourceParameter.getType(), requiredType.getPrimitiveType())) {
-                        return true;
-                    }
-                }
-
-                signatureIndex++;
-            }
-            return false;
-        }
-
-        private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean typedCasts) {
-            NodeData node = execution.getChild().getNodeData();
-
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-
-            TypeData sourceType = source.getTypeSystemType();
-
-            if (!sourceType.needsCastTo(targetType)) {
-                return null;
-            }
-
-            builder.startGroup();
-
-            if (execution.isShortCircuit()) {
-                ActualParameter shortCircuit = source.getPreviousParameter();
-                assert shortCircuit != null;
-                builder.string("(");
-                builder.string("!").string(valueName(shortCircuit));
-                builder.string(" || ");
-            }
-
-            String castMethodName;
-            String castTypeName = null;
-            List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
-            if (types.size() > 1) {
-                castMethodName = TypeSystemCodeGenerator.isImplicitTypeMethodName(targetType);
-                if (typedCasts) {
-                    castTypeName = implicitTypeName(source);
-                }
-            } else {
-                castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType);
-            }
-
-            startCallTypeSystemMethod(builder, node.getTypeSystem(), castMethodName);
-            builder.string(valueName(source));
-            if (castTypeName != null) {
-                builder.string(castTypeName);
-            }
-            builder.end().end(); // call
-
-            if (execution.isShortCircuit()) {
-                builder.string(")");
-            }
-
-            builder.end(); // group
-
-            return builder.getRoot();
-        }
-
-        // TODO merge redundancies with #createTypeGuard
-        private CodeTree createCast(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean typedCasts) {
-            NodeData node = execution.getChild().getNodeData();
-            TypeData sourceType = source.getTypeSystemType();
-
-            if (!sourceType.needsCastTo(targetType)) {
-                return null;
-            }
-
-            CodeTree condition = null;
-            if (execution.isShortCircuit()) {
-                ActualParameter shortCircuit = source.getPreviousParameter();
-                assert shortCircuit != null;
-                condition = CodeTreeBuilder.singleString(valueName(shortCircuit));
-            }
-
-            String castMethodName;
-            String castTypeName = null;
-            List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
-            if (types.size() > 1) {
-                castMethodName = TypeSystemCodeGenerator.asImplicitTypeMethodName(targetType);
-                if (typedCasts) {
-                    castTypeName = implicitTypeName(source);
-                }
-            } else {
-                castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
-            }
-
-            List<CodeTree> args = new ArrayList<>();
-            args.add(CodeTreeBuilder.singleString(valueName(source)));
-            if (castTypeName != null) {
-                args.add(CodeTreeBuilder.singleString(castTypeName));
-            }
-
-            CodeTree cast = createCallTypeSystemMethod(parent, node, castMethodName, args.toArray(new CodeTree[0]));
-
-            CodeTreeBuilder builder = parent.create();
-            builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, cast));
-
-            return builder.getRoot();
-        }
-
-        private CodeTree createGetImplicitType(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType) {
-            CodeTree condition = null;
-            if (execution.isShortCircuit()) {
-                ActualParameter shortCircuit = source.getPreviousParameter();
-                assert shortCircuit != null;
-                condition = CodeTreeBuilder.singleString(valueName(shortCircuit));
-            }
-
-            CodeTreeBuilder builder = parent.create();
-            List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
-            if (types.size() > 1) {
-                CodeTree castType = createCallTypeSystemMethod(parent, execution.getChild().getNodeData(), TypeSystemCodeGenerator.getImplicitClass(targetType),
-                                CodeTreeBuilder.singleString(valueName(source)));
-                builder.tree(createLazyAssignment(builder, implicitTypeName(source), getContext().getType(Class.class), condition, castType));
-            }
-            return builder.getRoot();
-        }
-
-        private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardExpression guard) {
-            CodeTreeBuilder builder = parent.create();
-            builder.string(prefix);
-            if (guard.isNegated()) {
-                builder.string("!");
-            }
-            builder.tree(createTemplateMethodCall(builder, null, source, guard.getResolvedGuard(), null));
-            return builder.getRoot();
-        }
-
-        protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) {
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-
-            if (current.getMethod() == null) {
-                emitEncounteredSynthetic(builder, current);
-            } else {
-                builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end();
-            }
-
-            return encloseThrowsWithFallThrough(current, builder.getRoot());
-        }
-
-        private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree) {
-            if (current.getExceptions().isEmpty()) {
-                return tree;
-            }
-            CodeTreeBuilder builder = new CodeTreeBuilder(null);
-
-            builder.startTryBlock();
-            builder.tree(tree);
-            for (SpecializationThrowsData exception : current.getExceptions()) {
-                builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx");
-                builder.tree(createDeoptimize(builder));
-                builder.tree(createCallRewriteMonomorphic(builder, false, current.getNode().getGenericSpecialization().getReturnType().getTypeSystemType(), current, null,
-                                "Thrown " + Utils.getSimpleName(exception.getJavaClass())));
-            }
-            builder.end();
-
-            return builder.getRoot();
-        }
-
-        protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) {
-            TypeData type = executable.getType();
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            NodeData node = specialization.getNode();
-
-            TypeData primaryType = castExecutable.getType();
-
-            boolean needsTry = castExecutable.hasUnexpectedValue(getContext());
-            boolean returnVoid = type.isVoid();
-
-            List<ActualParameter> executeParameters = new ArrayList<>();
-            for (ActualParameter sourceParameter : executable.getSignatureParameters()) {
-                ActualParameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName());
-                if (targetParameter != null) {
-                    executeParameters.add(targetParameter);
-                }
-            }
-
-            // execute names are enforced no cast
-            String[] executeParameterNames = new String[executeParameters.size()];
-            for (int i = 0; i < executeParameterNames.length; i++) {
-                executeParameterNames[i] = valueName(executeParameters.get(i));
-            }
-
-            builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null));
-            boolean hasUnexpected = executable.hasUnexpectedValue(getContext());
-
-            CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames);
-            if (needsTry) {
-                if (!returnVoid) {
-                    builder.declaration(primaryType.getPrimitiveType(), "value");
-                }
-                builder.startTryBlock();
-
-                if (returnVoid) {
-                    builder.statement(primaryExecuteCall);
-                } else {
-                    builder.startStatement();
-                    builder.string("value = ");
-                    builder.tree(primaryExecuteCall);
-                    builder.end();
-                }
-
-                builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
-                if (returnVoid) {
-                    builder.string("// ignore").newLine();
-                } else {
-                    builder.startReturn();
-                    builder.tree(createExpectExecutableType(node, specialization.getNode().getTypeSystem().getGenericTypeData(), hasUnexpected, executable.getType(),
-                                    CodeTreeBuilder.singleString("ex.getResult()")));
-                    builder.end();
-                }
-                builder.end();
-
-                if (!returnVoid) {
-                    builder.startReturn();
-                    builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), hasUnexpected, executable.getType(), CodeTreeBuilder.singleString("value")));
-                    builder.end();
-                }
-            } else {
-                if (returnVoid) {
-                    builder.statement(primaryExecuteCall);
-                } else {
-                    builder.startReturn();
-                    builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), hasUnexpected, executable.getType(), primaryExecuteCall));
-                    builder.end();
-                }
-            }
-
-            return builder.getRoot();
-        }
-
-        protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, boolean hasUnexpected, TypeData exepctedType, CodeTree value) {
-            return createCastType(node.getTypeSystem(), sourceType, exepctedType, hasUnexpected, value);
-        }
-
-        protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters,
-                        ActualParameter unexpectedParameter) {
-            CodeTreeBuilder builder = parent.create();
-            for (ActualParameter targetParameter : targetParameters) {
-                if (!targetParameter.getSpecification().isSignature()) {
-                    continue;
-                }
-                NodeExecutionData execution = targetParameter.getSpecification().getExecution();
-                CodeTree executionExpressions = createExecuteChild(builder, execution, sourceExecutable, targetParameter, unexpectedParameter);
-                CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, specialization, sourceExecutable, targetParameter, execution.isShortCircuit(), unexpectedParameter);
-                CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, specialization, targetParameter, unexpectedParameter);
-
-                if (shortCircuitTree == executionExpressions) {
-                    if (containsNewLine(executionExpressions)) {
-                        builder.declaration(targetParameter.getType(), valueName(targetParameter));
-                        builder.tree(shortCircuitTree);
-                    } else {
-                        builder.startStatement().type(targetParameter.getType()).string(" ").tree(shortCircuitTree).end();
-                    }
-                } else {
-                    builder.tree(shortCircuitTree);
-                }
-
-            }
-            return builder.getRoot();
-        }
-
-        private ExecutableTypeData resolveExecutableType(NodeExecutionData execution, TypeData type) {
-            ExecutableTypeData targetExecutable = execution.getChild().findExecutableType(getContext(), type);
-            if (targetExecutable == null) {
-                targetExecutable = execution.getChild().findAnyGenericExecutableType(getContext());
-            }
-            return targetExecutable;
-        }
-
-        private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, ActualParameter targetParameter,
-                        ActualParameter unexpectedParameter) {
-            SpecializationData specialization = getModel();
-            TreeSet<TypeData> possiblePolymorphicTypes = lookupPolymorphicTargetTypes(targetParameter);
-            if (specialization.isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null && possiblePolymorphicTypes.size() > 1) {
-
-                CodeTreeBuilder builder = parent.create();
-
-                boolean elseIf = false;
-                for (TypeData possiblePolymoprhicType : possiblePolymorphicTypes) {
-                    if (possiblePolymoprhicType.isGeneric()) {
-                        continue;
-                    }
-                    elseIf = builder.startIf(elseIf);
-
-                    ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName());
-                    TypeData sourceType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null;
-                    builder.string(polymorphicTypeName(targetParameter.getSpecification().getExecution())).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType());
-                    builder.end().startBlock();
-                    builder.startStatement();
-                    builder.tree(createExecuteChildExpression(parent, execution, sourceType, new ActualParameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null));
-                    builder.end();
-                    builder.end();
-                }
-
-                builder.startElseBlock();
-                builder.startStatement().tree(createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter)).end();
-                builder.end();
-
-                return builder.getRoot();
-            } else {
-                return createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter);
-            }
-        }
-
-        protected final List<ActualParameter> getImplicitTypeParameters(SpecializationData model) {
-            List<ActualParameter> parameter = new ArrayList<>();
-            for (ActualParameter param : model.getSignatureParameters()) {
-                NodeChildData child = param.getSpecification().getExecution().getChild();
-                List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
-                if (types.size() > 1) {
-                    parameter.add(param);
-                }
-            }
-            return parameter;
-        }
-
-        protected final TreeSet<TypeData> lookupPolymorphicTargetTypes(ActualParameter param) {
-            SpecializationData specialization = getModel();
-            TreeSet<TypeData> possiblePolymorphicTypes = new TreeSet<>();
-            for (SpecializationData otherSpecialization : specialization.getNode().getSpecializations()) {
-                if (!otherSpecialization.isSpecialized()) {
-                    continue;
-                }
-                ActualParameter otherParameter = otherSpecialization.findParameter(param.getLocalName());
-                if (otherParameter != null) {
-                    possiblePolymorphicTypes.add(otherParameter.getTypeSystemType());
-                }
-            }
-            return possiblePolymorphicTypes;
-        }
-
-        private CodeTree createExecuteChildImplicit(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, ActualParameter param, ActualParameter unexpectedParameter) {
-            CodeTreeBuilder builder = parent.create();
-            ActualParameter sourceParameter = sourceExecutable.findParameter(param.getLocalName());
-            String childExecuteName = createExecuteChildMethodName(param, sourceParameter != null);
-            if (childExecuteName != null) {
-                builder.string(valueName(param));
-                builder.string(" = ");
-                builder.startCall(childExecuteName);
-
-                for (ActualParameter parameters : sourceExecutable.getParameters()) {
-                    if (parameters.getSpecification().isSignature()) {
-                        continue;
-                    }
-                    builder.string(parameters.getLocalName());
-                }
-
-                if (sourceParameter != null) {
-                    builder.string(valueNameEvaluated(sourceParameter));
-                }
-
-                builder.string(implicitTypeName(param));
-
-                builder.end();
-            } else {
-                List<TypeData> sourceTypes = execution.getChild().getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
-                TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null;
-                if (sourceTypes.size() > 1) {
-                    builder.tree(createExecuteChildImplicitExpressions(parent, param, expectType));
-                } else {
-                    builder.tree(createExecuteChildExpression(parent, execution, expectType, param, unexpectedParameter, null));
-                }
-            }
-            return builder.getRoot();
-        }
-
-        private String createExecuteChildMethodName(ActualParameter param, boolean expect) {
-            NodeExecutionData execution = param.getSpecification().getExecution();
-            NodeChildData child = execution.getChild();
-            if (child.getExecuteWith().size() > 0) {
-                return null;
-            }
-            List<TypeData> sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
-            if (sourceTypes.size() <= 1) {
-                return null;
-            }
-            String prefix = expect ? "expect" : "execute";
-            String suffix = execution.getIndex() > -1 ? String.valueOf(execution.getIndex()) : "";
-            return prefix + Utils.firstLetterUpperCase(child.getName()) + Utils.firstLetterUpperCase(Utils.getSimpleName(param.getType())) + suffix;
-        }
-
-        private List<CodeExecutableElement> createExecuteChilds(ActualParameter param, Set<TypeData> expectTypes) {
-            CodeExecutableElement executeMethod = createExecuteChild(param, null);
-            if (executeMethod == null) {
-                return Collections.emptyList();
-            }
-            List<CodeExecutableElement> childs = new ArrayList<>();
-            childs.add(executeMethod);
-
-            for (TypeData expectType : expectTypes) {
-                CodeExecutableElement method = createExecuteChild(param, expectType);
-                if (method != null) {
-                    childs.add(method);
-                }
-            }
-            return childs;
-        }
-
-        private CodeExecutableElement createExecuteChild(ActualParameter param, TypeData expectType) {
-            String childExecuteName = createExecuteChildMethodName(param, expectType != null);
-            if (childExecuteName == null) {
-                return null;
-            }
-
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, expectType != null ? STATIC : FINAL), param.getType(), childExecuteName);
-            method.getThrownTypes().add(getContext().getTruffleTypes().getUnexpectedValueException());
-            method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
-            if (expectType != null) {
-                method.addParameter(new CodeVariableElement(expectType.getPrimitiveType(), valueNameEvaluated(param)));
-            }
-            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param)));
-
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.declaration(param.getType(), valueName(param));
-            builder.tree(createExecuteChildImplicitExpressions(builder, param, expectType));
-            builder.startReturn().string(valueName(param)).end();
-
-            return method;
-        }
-
-        private CodeTree createExecuteChildImplicitExpressions(CodeTreeBuilder parent, ActualParameter targetParameter, TypeData expectType) {
-            CodeTreeBuilder builder = parent.create();
-            NodeData node = getModel().getNode();
-            NodeExecutionData execution = targetParameter.getSpecification().getExecution();
-            List<TypeData> sourceTypes = node.getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType());
-            boolean elseIf = false;
-            int index = 0;
-            for (TypeData sourceType : sourceTypes) {
-                if (index < sourceTypes.size() - 1) {
-                    elseIf = builder.startIf(elseIf);
-                    builder.string(implicitTypeName(targetParameter)).string(" == ").typeLiteral(sourceType.getPrimitiveType());
-                    builder.end();
-                    builder.startBlock();
-                } else {
-                    builder.startElseBlock();
-                }
-
-                ExecutableTypeData implictExecutableTypeData = execution.getChild().findExecutableType(getContext(), sourceType);
-                if (implictExecutableTypeData == null) {
-                    /*
-                     * For children with executeWith.size() > 0 an executable type may not exist so
-                     * use the generic executable type which is guaranteed to exist. An expect call
-                     * is inserted automatically by #createExecuteExpression.
-                     */
-                    implictExecutableTypeData = execution.getChild().getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), execution.getChild().getExecuteWith().size());
-                }
-
-                ImplicitCastData cast = execution.getChild().getNodeData().getTypeSystem().lookupCast(sourceType, targetParameter.getTypeSystemType());
-                CodeTree execute = createExecuteChildExpression(builder, execution, expectType, targetParameter, null, cast);
-                builder.statement(execute);
-                builder.end();
-                index++;
-            }
-            return builder.getRoot();
-        }
-
-        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData execution, TypeData sourceParameterType, ActualParameter targetParameter,
-                        ActualParameter unexpectedParameter, ImplicitCastData cast) {
-            // assignments: targetType <- castTargetType <- castSourceType <- sourceType
-            TypeData sourceType = sourceParameterType;
-            TypeData targetType = targetParameter.getTypeSystemType();
-            TypeData castSourceType = targetType;
-            TypeData castTargetType = targetType;
-
-            if (cast != null) {
-                castSourceType = cast.getSourceType();
-                castTargetType = cast.getTargetType();
-            }
-
-            CodeTree expression;
-            if (sourceType == null) {
-                ExecutableTypeData targetExecutable = resolveExecutableType(execution, castSourceType);
-                expression = createExecuteChildExpression(parent, execution, targetExecutable, unexpectedParameter);
-                sourceType = targetExecutable.getType();
-            } else {
-                expression = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter));
-            }
-
-            // target = expectTargetType(implicitCast(expectCastSourceType(source)))
-            TypeSystemData typeSystem = execution.getChild().getNodeData().getTypeSystem();
-            expression = createExpectType(typeSystem, sourceType, castSourceType, expression);
-            expression = createImplicitCast(parent, typeSystem, cast, expression);
-            expression = createExpectType(typeSystem, castTargetType, targetType, expression);
-
-            CodeTreeBuilder builder = parent.create();
-            builder.string(valueName(targetParameter));
-            builder.string(" = ");
-            builder.tree(expression);
-            return builder.getRoot();
-        }
-
-        private CodeTree createImplicitCast(CodeTreeBuilder parent, TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) {
-            if (cast == null) {
-                return expression;
-            }
-            CodeTreeBuilder builder = parent.create();
-            startCallTypeSystemMethod(builder, typeSystem, cast.getMethodName());
-            builder.tree(expression);
-            builder.end().end();
-            return builder.getRoot();
-        }
-
-        private boolean containsNewLine(CodeTree tree) {
-            if (tree.getCodeKind() == CodeTreeKind.NEW_LINE) {
-                return true;
-            }
-
-            for (CodeTree codeTree : tree.getEnclosedElements()) {
-                if (containsNewLine(codeTree)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private boolean hasUnexpected(ActualParameter sourceParameter, ActualParameter targetParameter, ActualParameter unexpectedParameter) {
-            NodeExecutionData execution = targetParameter.getSpecification().getExecution();
-
-            if (getModel().isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) {
-                // check for other polymorphic types
-                TreeSet<TypeData> polymorphicTargetTypes = lookupPolymorphicTargetTypes(targetParameter);
-                if (polymorphicTargetTypes.size() > 1) {
-                    for (TypeData polymorphicTargetType : polymorphicTargetTypes) {
-                        if (hasUnexpectedType(execution, sourceParameter, polymorphicTargetType)) {
-                            return true;
-                        }
-                    }
-                }
-            }
-
-            if (hasUnexpectedType(execution, sourceParameter, targetParameter.getTypeSystemType())) {
-                return true;
-            }
-            return false;
-        }
-
-        private boolean hasUnexpectedType(NodeExecutionData execution, ActualParameter sourceParameter, TypeData targetType) {
-            List<TypeData> implicitSourceTypes = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
-
-            for (TypeData implicitSourceType : implicitSourceTypes) {
-                TypeData sourceType;
-                ExecutableTypeData targetExecutable = resolveExecutableType(execution, implicitSourceType);
-                if (sourceParameter != null) {
-                    sourceType = sourceParameter.getTypeSystemType();
-                } else {
-                    if (targetExecutable.hasUnexpectedValue(getContext())) {
-                        return true;
-                    }
-                    sourceType = targetExecutable.getType();
-                }
-
-                ImplicitCastData cast = getModel().getNode().getTypeSystem().lookupCast(implicitSourceType, targetType);
-                if (cast != null) {
-                    if (cast.getSourceType().needsCastTo(targetType)) {
-                        return true;
-                    }
-                }
-
-                if (sourceType.needsCastTo(targetType)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ExecutableTypeData currentExecutable, ActualParameter param,
-                        boolean shortCircuit, ActualParameter unexpectedParameter) {
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            ActualParameter sourceParameter = currentExecutable.findParameter(param.getLocalName());
-            boolean unexpected = hasUnexpected(sourceParameter, param, unexpectedParameter);
-            if (!unexpected) {
-                return body;
-            }
-
-            if (!shortCircuit) {
-                builder.declaration(param.getType(), valueName(param));
-            }
-            builder.startTryBlock();
-
-            if (containsNewLine(body)) {
-                builder.tree(body);
-            } else {
-                builder.statement(body);
-            }
-
-            builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
-            SpecializationData generic = specialization.getNode().getGenericSpecialization();
-            ActualParameter genericParameter = generic.findParameter(param.getLocalName());
-
-            List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter);
-            builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter));
-            if (specialization.isPolymorphic()) {
-                builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param));
-            } else {
-                builder.tree(createCallRewriteMonomorphic(builder, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), specialization, param,
-                                "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType())));
-            }
-            builder.end(); // catch block
-
-            return builder.getRoot();
-        }
-
-        private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, ActualParameter param) {
-            NodeData node = specialization.getNode();
-            SpecializationData polymorphic = node.getPolymorphicSpecialization();
-
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            builder.startStatement().string(polymorphicTypeName(param.getSpecification().getExecution())).string(" = ").typeLiteral(getContext().getType(Object.class)).end();
-
-            builder.startReturn();
-
-            CodeTreeBuilder execute = new CodeTreeBuilder(builder);
-            execute.startCall("next0", EXECUTE_CHAINED);
-            addInternalValueParameterNames(execute, specialization, polymorphic, param.getLocalName(), true, null);
-            execute.end();
-
-            TypeData sourceType = polymorphic.getReturnType().getTypeSystemType();
-
-            builder.tree(createExpectExecutableType(node, sourceType, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), execute.getRoot()));
-
-            builder.end();
-            return builder.getRoot();
-        }
-
-        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData targetExecution, ExecutableTypeData targetExecutable, ActualParameter unexpectedParameter) {
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            if (targetExecution != null) {
-                builder.tree(createAccessChild(targetExecution, null));
-                builder.string(".");
-            }
-
-            builder.startCall(targetExecutable.getMethodName());
-
-            // TODO this should be merged with #createTemplateMethodCall
-            int index = 0;
-            for (ActualParameter parameter : targetExecutable.getParameters()) {
-
-                if (!parameter.getSpecification().isSignature()) {
-                    builder.string(parameter.getLocalName());
-                } else {
-
-                    if (index < targetExecution.getChild().getExecuteWith().size()) {
-                        NodeChildData child = targetExecution.getChild().getExecuteWith().get(index);
-
-                        ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName());
-                        List<ActualParameter> specializationParams = getModel().findParameters(spec);
-
-                        if (specializationParams.isEmpty()) {
-                            builder.defaultValue(parameter.getType());
-                            continue;
-                        }
-
-                        ActualParameter specializationParam = specializationParams.get(0);
-
-                        TypeData targetType = parameter.getTypeSystemType();
-                        TypeData sourceType = specializationParam.getTypeSystemType();
-                        String localName = specializationParam.getLocalName();
-
-                        if (unexpectedParameter != null && unexpectedParameter.getLocalName().equals(specializationParam.getLocalName())) {
-                            localName = "ex.getResult()";
-                            sourceType = getModel().getNode().getTypeSystem().getGenericTypeData();
-                        }
-
-                        CodeTree value = CodeTreeBuilder.singleString(localName);
-
-                        if (sourceType.needsCastTo(targetType)) {
-                            value = createCallTypeSystemMethod(builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value);
-                        }
-                        builder.tree(value);
-                    } else {
-                        builder.defaultValue(parameter.getType());
-                    }
-                    index++;
-                }
-            }
-
-            builder.end();
-
-            return builder.getRoot();
-        }
-
-        private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) {
-            NodeExecutionData execution = parameter.getSpecification().getExecution();
-            if (execution == null || !execution.isShortCircuit()) {
-                return body;
-            }
-
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter);
-            builder.tree(createShortCircuitValue(builder, specialization, execution, shortCircuitParam, exceptionParam));
-            builder.declaration(parameter.getType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getType()));
-            builder.startIf().string(shortCircuitParam.getLocalName()).end();
-            builder.startBlock();
-
-            if (containsNewLine(body)) {
-                builder.tree(body);
-            } else {
-                builder.statement(body);
-            }
-            builder.end();
-
-            return builder.getRoot();
-        }
-
-        private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeExecutionData execution, ActualParameter shortCircuitParam,
-                        ActualParameter exceptionParam) {
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            int shortCircuitIndex = 0;
-            for (NodeExecutionData otherExectuion : specialization.getNode().getChildExecutions()) {
-                if (otherExectuion.isShortCircuit()) {
-                    if (otherExectuion == execution) {
-                        break;
-                    }
-                    shortCircuitIndex++;
-                }
-            }
-
-            builder.startStatement().type(shortCircuitParam.getType()).string(" ").string(valueName(shortCircuitParam)).string(" = ");
-            ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex);
-            builder.tree(createTemplateMethodCall(builder, null, specialization, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null));
-            builder.end(); // statement
-
-            return builder.getRoot();
-        }
-
-        protected CodeTree createCallRewriteMonomorphic(CodeTreeBuilder parent, boolean hasUnexpected, TypeData returnType, SpecializationData current, ActualParameter exceptionParam, String reason) {
-            NodeData node = current.getNode();
-            SpecializationData generic = node.getGenericSpecialization();
-            CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
-            specializeCall.startCall(REWRITE);
-            addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, null);
-            specializeCall.doubleQuote(reason);
-            specializeCall.end().end();
-
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-
-            builder.startReturn();
-            builder.tree(createExpectExecutableType(node, generic.getReturnType().getTypeSystemType(), hasUnexpected, returnType, specializeCall.getRoot()));
-            builder.end();
-
-            return builder.getRoot();
-        }
-
-    }
-
-    private class PolymorphicNodeFactory extends SpecializedNodeFactory {
-
-        public PolymorphicNodeFactory(CodeTypeElement nodeGen) {
-            super(nodeGen);
-        }
-
-        @Override
-        public CodeTypeElement create(SpecializationData polymorph) {
-            NodeData node = polymorph.getNode();
-            TypeMirror baseType = node.getNodeType();
-            if (nodeGen != null) {
-                baseType = nodeGen.asType();
-            }
-            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false);
-
-            clazz.getAnnotationMirrors().add(createNodeInfo(node, NodeCost.POLYMORPHIC));
-
-            for (ActualParameter polymorphParameter : polymorph.getSignatureParameters()) {
-                if (!polymorphParameter.getTypeSystemType().isGeneric()) {
-                    continue;
-                }
-                Set<TypeData> types = new HashSet<>();
-                for (SpecializationData specialization : node.getSpecializations()) {
-                    if (!specialization.isSpecialized()) {
-                        continue;
-                    }
-                    ActualParameter parameter = specialization.findParameter(polymorphParameter.getLocalName());
-                    assert parameter != null;
-                    types.add(parameter.getTypeSystemType());
-                }
-
-            }
-
-            for (NodeExecutionData execution : getModel().getNode().getChildExecutions()) {
-                String fieldName = polymorphicTypeName(execution);
-                CodeVariableElement var = new CodeVariableElement(modifiers(PRIVATE), getContext().getType(Class.class), fieldName);
-                var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getCompilationFinal()));
-                clazz.add(var);
-            }
-
-            return clazz;
-        }
-
-        @Override
-        protected void createChildren(SpecializationData specialization) {
-            CodeTypeElement clazz = getElement();
-
-            createConstructors(clazz);
-            createExecuteMethods(specialization);
-
-            clazz.add(createUpdateTypes0());
-            createCachedExecuteMethods(specialization);
-        }
-
-    }
-
-    private class SpecializedNodeFactory extends NodeBaseFactory {
-
-        protected final CodeTypeElement nodeGen;
-
-        public SpecializedNodeFactory(CodeTypeElement nodeGen) {
-            this.nodeGen = nodeGen;
-        }
-
-        @Override
-        public CodeTypeElement create(SpecializationData specialization) {
-            NodeData node = specialization.getNode();
-            TypeMirror baseType = node.getNodeType();
-            if (nodeGen != null) {
-                baseType = nodeGen.asType();
-            }
-            CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false);
-
-            if (specialization.isSpecialized() || specialization.isUninitialized()) {
-                clazz.add(createGetMetadata0(false));
-                clazz.add(createMetadataLiteral());
-            }
-
-            NodeCost cost;
-            if (specialization.isGeneric()) {
-                cost = NodeCost.MEGAMORPHIC;
-            } else if (specialization.isUninitialized()) {
-                cost = NodeCost.UNINITIALIZED;
-            } else if (specialization.isPolymorphic()) {
-                cost = NodeCost.POLYMORPHIC;
-            } else if (specialization.isSpecialized()) {
-                cost = NodeCost.MONOMORPHIC;
-            } else {
-                throw new AssertionError();
-            }
-            clazz.getAnnotationMirrors().add(createNodeInfo(node, cost));
-
-            if (specialization.isUninitialized() && node.getGenericSpecialization().isReachable()) {
-                clazz.add(createUninitializedGetCostOverride());
-            }
-
-            return clazz;
-        }
-
-        private Element createUninitializedGetCostOverride() {
-            TypeMirror returnType = context.getTruffleTypes().getNodeCost();
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getCost");
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.startIf().string(CONTAINS_FALLBACK).end().startBlock();
-            builder.startReturn().staticReference(returnType, "MONOMORPHIC").end();
-            builder.end();
-            builder.startReturn().string("super.getCost()").end();
-            return method;
-        }
-
-        private CodeVariableElement createMetadataLiteral() {
-            CodeVariableElement includes = new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), context.getTruffleTypes().getDslMetadata(), METADATA_FIELD_NAME);
-
-            CodeTreeBuilder builder = includes.createInitBuilder();
-
-            SpecializationData specialization = getModel();
-            NodeData node = specialization.getNode();
-
-            Set<SpecializationData> contains = specialization.getContains();
-            if (specialization.isUninitialized()) {
-                contains = new HashSet<>();
-
-                SpecializationData polymorphic = node.getPolymorphicSpecialization();
-                if (polymorphic != null) {
-                    contains.addAll(polymorphic.getContains());
-                }
-                SpecializationData generic = node.getGenericSpecialization();
-                if (generic != null) {
-                    contains.addAll(generic.getContains());
-                }
-            }
-
-            builder.startNew(context.getTruffleTypes().getDslMetadata());
-            builder.startGroup().string(nodeSpecializationClassName(getModel()), ".class").end();
-            builder.tree(createSpecializationListLiteral(builder, contains));
-            builder.tree(createSpecializationListLiteral(builder, getModel().getExcludedBy()));
-            builder.tree(createSpecializationTypeLiteral(builder, SpecializationData.getSignatureTypes(getModel())));
-            builder.string("0").string("0");
-            builder.end();
-            return includes;
-        }
-
-        private CodeTree createSpecializationTypeLiteral(CodeTreeBuilder parent, List<TypeMirror> list) {
-            ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class));
-            CodeTreeBuilder builder = parent.create();
-
-            if (list.isEmpty()) {
-                builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
-            } else {
-                builder.startNewArray(classArray, null);
-                for (TypeMirror type : list) {
-                    builder.typeLiteral(type);
-                }
-                builder.end();
-            }
-
-            return builder.getRoot();
-        }
-
-        private CodeTree createSpecializationListLiteral(CodeTreeBuilder parent, Set<SpecializationData> list) {
-            ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class));
-            CodeTreeBuilder builder = parent.create();
-
-            if (list.isEmpty()) {
-                builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
-            } else {
-                builder.startNewArray(classArray, null);
-                for (SpecializationData specialization : list) {
-                    if (specialization.isGeneric() || specialization.isPolymorphic()) {
-                        specialization = getModel().getNode().getUninitializedSpecialization();
-                    }
-                    builder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end();
-                }
-                builder.end();
-            }
-
-            return builder.getRoot();
-        }
-
-        protected CodeAnnotationMirror createNodeInfo(NodeData node, NodeCost cost) {
-            String shortName = node.getShortName();
-            CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation());
-            if (shortName != null) {
-                nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName));
-            }
-
-            DeclaredType nodeinfoCost = getContext().getTruffleTypes().getNodeCost();
-            VariableElement varKind = Utils.findVariableElement(nodeinfoCost, cost.name());
-
-            nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("cost"), new CodeAnnotationValue(varKind));
-            return nodeInfoMirror;
-        }
-
-        @Override
-        protected void createChildren(SpecializationData specialization) {
-            CodeTypeElement clazz = getElement();
-            createConstructors(clazz);
-
-            createExecuteMethods(specialization);
-            createCachedExecuteMethods(specialization);
-
-            if (specialization.isUninitialized()) {
-                if (specialization.getNode().isFallbackReachable()) {
-                    CodeVariableElement var = new CodeVariableElement(modifiers(Modifier.PRIVATE), context.getType(boolean.class), CONTAINS_FALLBACK);
-                    var.addAnnotationMirror(new CodeAnnotationMirror(context.getTruffleTypes().getCompilationFinal()));
-                    clazz.add(var);
-                }
-                clazz.add(createExecuteUninitialized());
-            }
-
-            if (!specialization.isUninitialized() && specialization.getNode().needsRewrites(context)) {
-                clazz.add(createCopyConstructorFactoryMethod(nodeGen.asType(), specialization));
-            } else {
-                for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
-                    if (constructor.getParameters().size() == 1 && ((CodeVariableElement) constructor.getParameters().get(0)).getType().equals(nodeGen.asType())) {
-                        // skip copy constructor - not used
-                        continue;
-                    }
-                    clazz.add(createConstructorFactoryMethod(specialization, constructor));
-                }
-            }
-        }
-
-        protected void createConstructors(CodeTypeElement clazz) {
-            TypeElement superTypeElement = Utils.fromTypeMirror(clazz.getSuperclass());
-            SpecializationData specialization = getModel();
-            NodeData node = specialization.getNode();
-            for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) {
-                if (specialization.isUninitialized()) {
-                    // ignore copy constructors for uninitialized if not polymorphic
-                    if (isCopyConstructor(constructor) && !node.isPolymorphic(context)) {
-                        continue;
-                    }
-                } else if (node.getUninitializedSpecialization() != null) {
-                    // ignore others than copy constructors for specialized nodes
-                    if (!isCopyConstructor(constructor)) {
-                        continue;
-                    }
-                }
-
-                CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor);
-                if (superConstructor == null) {
-                    continue;
-                }
-                CodeTree body = superConstructor.getBodyTree();
-                CodeTreeBuilder builder = superConstructor.createBuilder();
-                builder.tree(body);
-
-                if (superConstructor != null) {
-                    for (ActualParameter param : getImplicitTypeParameters(getModel())) {
-                        clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param)));
-                        superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param)));
-
-                        builder.startStatement();
-                        builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param));
-                        builder.end();
-                    }
-
-                    clazz.add(superConstructor);
-                }
-            }
-        }
-
-        protected void createExecuteMethods(SpecializationData specialization) {
-            NodeData node = specialization.getNode();
-            CodeTypeElement clazz = getElement();
-
-            for (ExecutableTypeData execType : node.getExecutableTypes()) {
-                if (execType.isFinal()) {
-                    continue;
-                }
-                CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, true);
-                clazz.add(executeMethod);
-                CodeTreeBuilder builder = executeMethod.getBuilder();
-                CodeTree result = createExecuteBody(builder, specialization, execType);
-                if (result != null) {
-                    builder.tree(result);
-                } else {
-                    clazz.remove(executeMethod);
-                }
-            }
-        }
-
-        protected void createCachedExecuteMethods(SpecializationData specialization) {
-            NodeData node = specialization.getNode();
-            if (!node.isPolymorphic(context)) {
-                return;
-            }
-
-            CodeTypeElement clazz = getElement();
-
-            final SpecializationData polymorphic = node.getPolymorphicSpecialization();
-            ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_CHAINED);
-            CodeExecutableElement executeMethod = CodeExecutableElement.clone(getContext().getEnvironment(), executeCached);
-            executeMethod.getModifiers().remove(Modifier.ABSTRACT);
-            CodeTreeBuilder builder = executeMethod.createBuilder();
-
-            if (specialization.isPolymorphic()) {
-                builder.startReturn().startCall("this.next0", EXECUTE_CHAINED);
-                addInternalValueParameterNames(builder, polymorphic, polymorphic, null, true, null);
-                builder.end().end();
-            } else if (specialization.isUninitialized()) {
-                if (node.getGenericSpecialization().isReachable()) {
-                    builder.startIf().string("!containsFallback").end().startBlock();
-                    builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
-                    builder.end();
-                } else {
-                    builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
-                }
-                builder.startReturn().startCall("this", EXECUTE_UNINITIALIZED);
-                addInternalValueParameterNames(builder, polymorphic, polymorphic, null, true, null);
-                builder.end().end();
-            } else {
-                CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder);
-                elseBuilder.startReturn().startCall("this.next0", EXECUTE_CHAINED);
-                addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, null);
-                elseBuilder.end().end();
-
-                builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), new CodeBlock<SpecializationData>() {
-
-                    public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
-                        return createGenericInvoke(b, polymorphic, current);
-                    }
-                }, elseBuilder.getRoot(), false, true, true, false));
-            }
-            clazz.add(executeMethod);
-        }
-
-        private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) {
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-
-            List<ExecutableTypeData> primaryExecutes = findFunctionalExecutableType(specialization, execType.getEvaluatedCount());
-
-            if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) {
-                builder.tree(createFunctionalExecute(builder, specialization, execType));
-            } else if (needsCastingExecuteMethod(execType)) {
-                assert !primaryExecutes.isEmpty();
-                builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0)));
-            } else {
-                return null;
-            }
-
-            return builder.getRoot();
-        }
-
-        private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) {
-            CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod());
-
-            method.getAnnotationMirrors().clear();
-            for (VariableElement variable : method.getParameters()) {
-                variable.getAnnotationMirrors().clear();
-            }
-
-            CodeTreeBuilder builder = method.createBuilder();
-            int i = 0;
-            int signatureIndex = -1;
-            for (VariableElement param : method.getParameters()) {
-                CodeVariableElement var = CodeVariableElement.clone(param);
-                ActualParameter actualParameter = i < execType.getParameters().size() ? execType.getParameters().get(i) : null;
-                String name;
-                if (actualParameter != null) {
-                    if (actualParameter.getSpecification().isSignature()) {
-                        signatureIndex++;
-                    }
-
-                    if (evaluated && actualParameter.getSpecification().isSignature()) {
-                        name = valueNameEvaluated(actualParameter);
-                    } else {
-                        name = valueName(actualParameter);
-                    }
-
-                    int varArgCount = getModel().getSignatureSize() - signatureIndex;
-                    if (evaluated && actualParameter.isTypeVarArgs()) {
-                        ActualParameter baseVarArgs = actualParameter;
-                        name = valueName(baseVarArgs) + "Args";
-
-                        builder.startAssert().string(name).string(" != null").end();
-                        builder.startAssert().string(name).string(".length == ").string(String.valueOf(varArgCount)).end();
-                        if (varArgCount > 0) {
-                            List<ActualParameter> varArgsParameter = execType.getParameters().subList(i, execType.getParameters().size());
-                            for (ActualParameter varArg : varArgsParameter) {
-                                if (varArgCount <= 0) {
-                                    break;
-                                }
-                                TypeMirror type = baseVarArgs.getType();
-                                if (type.getKind() == TypeKind.ARRAY) {
-                                    type = ((ArrayType) type).getComponentType();
-                                }
-                                builder.declaration(type, valueNameEvaluated(varArg), name + "[" + varArg.getTypeVarArgsIndex() + "]");
-                                varArgCount--;
-                            }
-                        }
-                    }
-                } else {
-                    name = "arg" + i;
-                }
-                var.setName(name);
-                method.getParameters().set(i, var);
-                i++;
-            }
-
-            method.getAnnotationMirrors().clear();
-            method.getModifiers().remove(Modifier.ABSTRACT);
-            return method;
-        }
-
-        private boolean needsCastingExecuteMethod(ExecutableTypeData execType) {
-            if (execType.isAbstract()) {
-                return true;
-            }
-            if (execType.getType().isGeneric()) {
-                return true;
-            }
-            return false;
-        }
-
-        private List<ExecutableTypeData> findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) {
-            TypeData primaryType = specialization.getReturnType().getTypeSystemType();
-            List<ExecutableTypeData> otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount);
-
-            List<ExecutableTypeData> filteredTypes = new ArrayList<>();
-            for (ExecutableTypeData compareType : otherTypes) {
-                if (!Utils.typeEquals(compareType.getType().getPrimitiveType(), primaryType.getPrimitiveType())) {
-                    continue;
-                }
-                filteredTypes.add(compareType);
-            }
-
-            // no direct matches found use generic where the type is Object
-            if (filteredTypes.isEmpty()) {
-                for (ExecutableTypeData compareType : otherTypes) {
-                    if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(getContext())) {
-                        filteredTypes.add(compareType);
-                    }
-                }
-            }
-
-            if (filteredTypes.isEmpty()) {
-                for (ExecutableTypeData compareType : otherTypes) {
-                    if (compareType.getType().isGeneric()) {
-                        filteredTypes.add(compareType);
-                    }
-                }
-            }
-
-            return filteredTypes;
-        }
-
-        private CodeTree createFunctionalExecute(CodeTreeBuilder parent, final SpecializationData specialization, final ExecutableTypeData executable) {
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            if (specialization.isUninitialized()) {
-                builder.tree(createDeoptimize(builder));
-            }
-
-            builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null));
-
-            CodeTree returnSpecialized = null;
-
-            if (specialization.findNextSpecialization() != null) {
-                CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder);
-                returnBuilder.tree(createDeoptimize(builder));
-                returnBuilder.tree(createCallRewriteMonomorphic(builder, executable.hasUnexpectedValue(context), executable.getType(), specialization, null,
-                                "One of guards " + specialization.getGuards() + " failed"));
-                returnSpecialized = returnBuilder.getRoot();
-            }
-
-            builder.tree(createExecuteTree(builder, specialization, SpecializationGroup.create(specialization), new CodeBlock<SpecializationData>() {
-
-                public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
-                    return createExecute(b, executable, specialization);
-                }
-            }, returnSpecialized, false, false, false, false));
-
-            return builder.getRoot();
-        }
-
-        private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) {
-            NodeData node = specialization.getNode();
-            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            if (!specialization.getExceptions().isEmpty() || !specialization.getAssumptions().isEmpty()) {
-                builder.startTryBlock();
-            }
-
-            for (String assumption : specialization.getAssumptions()) {
-                builder.startStatement();
-                builder.string("this.").string(assumption).string(".check()");
-                builder.end();
-            }
-
-            CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent);
-            if (specialization.isPolymorphic()) {
-                returnBuilder.startCall("next0", EXECUTE_CHAINED);
-                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null);
-                returnBuilder.end();
-            } else if (specialization.isUninitialized()) {
-                returnBuilder.startCall(EXECUTE_UNINITIALIZED);
-                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, null);
-                returnBuilder.end();
-            } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
-                emitEncounteredSynthetic(builder, specialization);
-            } else {
-                returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null));
-            }
-
-            if (!returnBuilder.isEmpty()) {
-                TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType());
-                TypeData sourceType = specialization.getReturnType().getTypeSystemType();
-
-                builder.startReturn();
-                if (targetType == null || sourceType == null) {
-                    builder.tree(returnBuilder.getRoot());
-                } else if (sourceType.needsCastTo(targetType)) {
-                    String castMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType);
-                    if (!executable.hasUnexpectedValue(context)) {
-                        castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
-                    }
-                    builder.tree(createCallTypeSystemMethod(parent, node, castMethodName, returnBuilder.getRoot()));
-                } else {
-                    builder.tree(returnBuilder.getRoot());
-                }
-                builder.end();
-            }
-
-            if (!specialization.getExceptions().isEmpty()) {
-                for (SpecializationThrowsData exception : specialization.getExceptions()) {
-                    builder.end().startCatchBlock(exception.getJavaClass(), "ex");
-                    builder.tree(createDeoptimize(builder));
-                    builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), specialization, null,
-                                    "Thrown " + Utils.getSimpleName(exception.getJavaClass())));
-                }
-                builder.end();
-            }
-            if (!specialization.getAssumptions().isEmpty()) {
-                builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex");
-                builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), specialization, null, "Assumption failed"));
-                builder.end();
-            }
-
-            return builder.getRoot();
-        }
-
-        protected CodeExecutableElement createCopyConstructorFactoryMethod(TypeMirror baseType, SpecializationData specialization) {
-            List<ActualParameter> implicitTypeParams = getImplicitTypeParameters(specialization);
-            String baseName = "current";
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), FACTORY_METHOD_NAME);
-            method.addParameter(new CodeVariableElement(specialization.getNode().getNodeType(), baseName));
-            for (ActualParameter implicitTypeParam : implicitTypeParams) {
-                method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(implicitTypeParam)));
-            }
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.startReturn();
-            builder.startNew(getElement().asType());
-            builder.startGroup().cast(baseType, CodeTreeBuilder.singleString(baseName)).end();
-            for (ActualParameter param : implicitTypeParams) {
-                builder.string(implicitTypeName(param));
-            }
-            builder.end().end();
-            return method;
-        }
-
-        protected CodeExecutableElement createConstructorFactoryMethod(SpecializationData specialization, ExecutableElement constructor) {
-            List<? extends VariableElement> parameters = constructor.getParameters();
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), FACTORY_METHOD_NAME,
-                            parameters.toArray(new CodeVariableElement[parameters.size()]));
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.startReturn();
-            builder.startNew(getElement().asType());
-            for (VariableElement param : parameters) {
-                builder.string(((CodeVariableElement) param).getName());
-            }
-            builder.end().end();
-            return method;
-        }
-    }
-
-    private interface CodeBlock<T> {
-
-        CodeTree create(CodeTreeBuilder parent, T value);
-
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,516 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class NodeData extends Template implements Comparable<NodeData> {
-
-    private final String nodeId;
-    private final String shortName;
-    private final List<NodeData> enclosingNodes = new ArrayList<>();
-    private NodeData declaringNode;
-
-    private final TypeSystemData typeSystem;
-    private final List<NodeChildData> children;
-    private final List<NodeExecutionData> childExecutions;
-    private final List<NodeFieldData> fields;
-    private final List<String> assumptions;
-
-    private ParameterSpec instanceParameterSpec;
-
-    private final List<SpecializationData> specializations = new ArrayList<>();
-    private final List<ShortCircuitData> shortCircuits = new ArrayList<>();
-    private final List<CreateCastData> casts = new ArrayList<>();
-    private Map<Integer, List<ExecutableTypeData>> executableTypes;
-
-    private final NodeExecutionData thisExecution;
-
-    public NodeData(ProcessorContext context, TypeElement type, String shortName, TypeSystemData typeSystem, List<NodeChildData> children, List<NodeExecutionData> executions,
-                    List<NodeFieldData> fields, List<String> assumptions) {
-        super(context, type, null, null);
-        this.nodeId = type.getSimpleName().toString();
-        this.shortName = shortName;
-        this.typeSystem = typeSystem;
-        this.fields = fields;
-        this.children = children;
-        this.childExecutions = executions;
-        this.assumptions = assumptions;
-        this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, false);
-        this.thisExecution.getChild().setNode(this);
-        if (children != null) {
-            for (NodeChildData child : children) {
-                child.setParentNode(this);
-            }
-        }
-    }
-
-    public NodeData(ProcessorContext context, TypeElement type) {
-        this(context, type, null, null, null, null, null, null);
-    }
-
-    public NodeExecutionData getThisExecution() {
-        return thisExecution;
-    }
-
-    public boolean isFallbackReachable() {
-        SpecializationData generic = getGenericSpecialization();
-        if (generic != null) {
-            return generic.isReachable();
-        }
-        return false;
-    }
-
-    public void addEnclosedNode(NodeData node) {
-        this.enclosingNodes.add(node);
-        node.declaringNode = this;
-    }
-
-    public List<NodeExecutionData> getChildExecutions() {
-        return childExecutions;
-    }
-
-    public int getSignatureSize() {
-        if (getSpecializations() != null && !getSpecializations().isEmpty()) {
-            return getSpecializations().get(0).getSignatureSize();
-        }
-        return 0;
-    }
-
-    public boolean needsFrame(ProcessorContext context) {
-        for (SpecializationData specialization : specializations) {
-            if (!specialization.isReachable()) {
-                continue;
-            }
-            if (specialization.hasFrame(context)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public boolean needsImplicitCast(ProcessorContext context) {
-        for (NodeChildData child : getChildren()) {
-            if (child.needsImplicitCast(context)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public boolean isPolymorphic(ProcessorContext context) {
-        return needsRewrites(context);
-    }
-
-    public List<CreateCastData> getCasts() {
-        return casts;
-    }
-
-    public String getShortName() {
-        return shortName;
-    }
-
-    public List<NodeFieldData> getFields() {
-        return fields;
-    }
-
-    @Override
-    protected List<MessageContainer> findChildContainers() {
-        List<MessageContainer> containerChildren = new ArrayList<>();
-        if (enclosingNodes != null) {
-            containerChildren.addAll(enclosingNodes);
-        }
-        if (typeSystem != null) {
-            containerChildren.add(typeSystem);
-        }
-        if (specializations != null) {
-            for (MessageContainer specialization : specializations) {
-                if (specialization.getMessageElement() != null) {
-                    containerChildren.add(specialization);
-                }
-            }
-        }
-        if (executableTypes != null) {
-            containerChildren.addAll(getExecutableTypes());
-        }
-        if (shortCircuits != null) {
-            containerChildren.addAll(shortCircuits);
-        }
-        if (children != null) {
-            containerChildren.addAll(children);
-        }
-        if (fields != null) {
-            containerChildren.addAll(fields);
-        }
-        if (casts != null) {
-            containerChildren.addAll(casts);
-        }
-        return containerChildren;
-    }
-
-    public ParameterSpec getInstanceParameterSpec() {
-        return instanceParameterSpec;
-    }
-
-    public void setInstanceParameterSpec(ParameterSpec instanceParameter) {
-        this.instanceParameterSpec = instanceParameter;
-    }
-
-    public String getNodeId() {
-        return nodeId;
-    }
-
-    public TypeMirror getNodeType() {
-        return getTemplateType().asType();
-    }
-
-    public List<String> getAssumptions() {
-        return assumptions;
-    }
-
-    public boolean needsFactory() {
-        if (specializations == null) {
-            return false;
-        }
-        if (getTemplateType().getModifiers().contains(Modifier.PRIVATE)) {
-            return false;
-        }
-
-        boolean noSpecialization = true;
-        for (SpecializationData specialization : specializations) {
-            noSpecialization = noSpecialization && !specialization.isSpecialized();
-        }
-        return !noSpecialization;
-    }
-
-    public boolean supportsFrame() {
-        if (executableTypes != null) {
-            for (ExecutableTypeData execType : getExecutableTypes(-1)) {
-                if (execType.findParameter("frameValue") == null) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    public List<NodeData> getNodeDeclaringChildren() {
-        List<NodeData> nodeChildren = new ArrayList<>();
-        for (NodeData child : getEnclosingNodes()) {
-            if (child.needsFactory()) {
-                nodeChildren.add(child);
-            }
-            nodeChildren.addAll(child.getNodeDeclaringChildren());
-        }
-        return nodeChildren;
-    }
-
-    public NodeData getDeclaringNode() {
-        return declaringNode;
-    }
-
-    public List<NodeData> getEnclosingNodes() {
-        return enclosingNodes;
-    }
-
-    public List<TemplateMethod> getAllTemplateMethods() {
-        List<TemplateMethod> methods = new ArrayList<>();
-
-        for (SpecializationData specialization : getSpecializations()) {
-            methods.add(specialization);
-        }
-
-        methods.addAll(getExecutableTypes());
-        methods.addAll(getShortCircuits());
-        if (getCasts() != null) {
-            methods.addAll(getCasts());
-        }
-
-        return methods;
-    }
-
-    public ExecutableTypeData findGenericExecutableType(ProcessorContext context, TypeData type, int evaluatedCount) {
-        List<ExecutableTypeData> types = findGenericExecutableTypes(context, evaluatedCount);
-        for (ExecutableTypeData availableType : types) {
-            if (Utils.typeEquals(availableType.getType().getBoxedType(), type.getBoxedType())) {
-                return availableType;
-            }
-        }
-        return null;
-    }
-
-    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context, int evaluatedCount) {
-        List<ExecutableTypeData> types = findGenericExecutableTypes(context, evaluatedCount);
-        for (ExecutableTypeData type : types) {
-            if (type.getType().isGeneric()) {
-                return type;
-            }
-        }
-
-        for (ExecutableTypeData type : types) {
-            if (!type.getType().isVoid()) {
-                return type;
-            }
-        }
-
-        for (ExecutableTypeData type : types) {
-            return type;
-        }
-        return null;
-    }
-
-    public List<ExecutableTypeData> getExecutableTypes(int evaluatedCount) {
-        if (executableTypes == null) {
-            return Collections.emptyList();
-        }
-        if (evaluatedCount == -1) {
-            List<ExecutableTypeData> typeData = new ArrayList<>();
-            for (int currentEvaluationCount : executableTypes.keySet()) {
-                typeData.addAll(executableTypes.get(currentEvaluationCount));
-            }
-            return typeData;
-        } else {
-            List<ExecutableTypeData> types = executableTypes.get(evaluatedCount);
-            if (types == null) {
-                return Collections.emptyList();
-            }
-            return types;
-        }
-    }
-
-    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context, int evaluatedCount) {
-        List<ExecutableTypeData> types = new ArrayList<>();
-        for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) {
-            if (!type.hasUnexpectedValue(context)) {
-                types.add(type);
-            }
-        }
-        return types;
-    }
-
-    public ExecutableTypeData findExecutableType(TypeData prmitiveType, int evaluatedCount) {
-        for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) {
-            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().getTypeSystemType() == type) {
-                if (result != null) {
-                    // Result not unique;
-                    return null;
-                }
-                result = specialization;
-            }
-        }
-        return result;
-    }
-
-    public boolean needsRewrites(ProcessorContext context) {
-        boolean needsRewrites = false;
-
-        for (SpecializationData specialization : getSpecializations()) {
-            if (specialization.hasRewrite(context)) {
-                needsRewrites = true;
-                break;
-            }
-        }
-        return needsRewrites || getSpecializations().size() > 1;
-    }
-
-    public SpecializationData getPolymorphicSpecialization() {
-        for (SpecializationData specialization : specializations) {
-            if (specialization.isPolymorphic()) {
-                return specialization;
-            }
-        }
-        return null;
-    }
-
-    public SpecializationData getGenericSpecialization() {
-        for (SpecializationData specialization : specializations) {
-            if (specialization.isGeneric()) {
-                return specialization;
-            }
-        }
-        return null;
-    }
-
-    public SpecializationData getUninitializedSpecialization() {
-        for (SpecializationData specialization : specializations) {
-            if (specialization.isUninitialized()) {
-                return specialization;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public TypeSystemData getTypeSystem() {
-        return typeSystem;
-    }
-
-    public String dump() {
-        return dump(0);
-    }
-
-    private String dump(int level) {
-        String indent = "";
-        for (int i = 0; i < level; i++) {
-            indent += "    ";
-        }
-        StringBuilder builder = new StringBuilder();
-
-        builder.append(String.format("%s%s {", indent, toString()));
-
-        dumpProperty(builder, indent, "templateClass", Utils.getQualifiedName(getTemplateType()));
-        dumpProperty(builder, indent, "typeSystem", getTypeSystem());
-        dumpProperty(builder, indent, "fields", getChildren());
-        dumpProperty(builder, indent, "executableTypes", getExecutableTypes());
-        dumpProperty(builder, indent, "specializations", getSpecializations());
-        dumpProperty(builder, indent, "assumptions", getAssumptions());
-        dumpProperty(builder, indent, "casts", getCasts());
-        dumpProperty(builder, indent, "messages", collectMessages());
-        if (getEnclosingNodes().size() > 0) {
-            builder.append(String.format("\n%s  children = [", indent));
-            for (NodeData node : getEnclosingNodes()) {
-                builder.append("\n");
-                builder.append(node.dump(level + 1));
-            }
-            builder.append(String.format("\n%s  ]", indent));
-        }
-        builder.append(String.format("%s}", indent));
-        return builder.toString();
-    }
-
-    private static void dumpProperty(StringBuilder b, String indent, String propertyName, Object value) {
-        if (value instanceof List) {
-            List<?> list = (List<?>) value;
-            if (!list.isEmpty()) {
-                b.append(String.format("\n%s  %s = %s", indent, propertyName, dumpList(indent, (List<?>) value)));
-            }
-        } else {
-            if (value != null) {
-                b.append(String.format("\n%s  %s = %s", indent, propertyName, value));
-            }
-        }
-    }
-
-    private static String dumpList(String indent, List<?> array) {
-        if (array == null) {
-            return "null";
-        }
-
-        if (array.isEmpty()) {
-            return "[]";
-        } else if (array.size() == 1) {
-            return "[" + array.get(0).toString() + "]";
-        }
-
-        StringBuilder b = new StringBuilder();
-        b.append("[");
-        for (Object object : array) {
-            b.append("\n        ");
-            b.append(indent);
-            b.append(object);
-            b.append(", ");
-        }
-        b.append("\n    ").append(indent).append("]");
-        return b.toString();
-    }
-
-    public NodeExecutionData findExecution(String name) {
-        if (getChildExecutions() == null) {
-            return null;
-        }
-        for (NodeExecutionData execution : getChildExecutions()) {
-            if (execution.getName().equals(name)) {
-                return execution;
-            }
-        }
-        return null;
-    }
-
-    public NodeChildData findChild(String name) {
-        for (NodeChildData field : getChildren()) {
-            if (field.getName().equals(name)) {
-                return field;
-            }
-        }
-        return null;
-    }
-
-    public List<NodeChildData> getChildren() {
-        return children;
-    }
-
-    public List<SpecializationData> getSpecializations() {
-        return specializations;
-    }
-
-    public List<ExecutableTypeData> getExecutableTypes() {
-        return getExecutableTypes(-1);
-    }
-
-    public List<ShortCircuitData> getShortCircuits() {
-        return shortCircuits;
-    }
-
-    public void setExecutableTypes(Map<Integer, List<ExecutableTypeData>> executableTypes) {
-        this.executableTypes = executableTypes;
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + "[" + getNodeId() + "]";
-    }
-
-    public CreateCastData findCast(String name) {
-        if (getCasts() != null) {
-            for (CreateCastData cast : getCasts()) {
-                if (cast.getChildNames().contains(name)) {
-                    return cast;
-                }
-            }
-        }
-        return null;
-    }
-
-    public int compareTo(NodeData o) {
-        return getNodeId().compareTo(o.getNodeId());
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeExecutionData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality;
-
-public class NodeExecutionData {
-
-    private final NodeChildData child;
-    private final String name;
-    private final int index;
-    private final boolean shortCircuit;
-
-    public NodeExecutionData(NodeChildData child, int index, boolean shortCircuit) {
-        this.child = child;
-        this.index = index;
-        this.shortCircuit = shortCircuit;
-        this.name = createName();
-    }
-
-    private String createName() {
-        if (isIndexed()) {
-            return child.getName() + index;
-        }
-        return child.getName();
-    }
-
-    public TypeMirror getNodeType() {
-        TypeMirror type;
-        if (child.getCardinality() == Cardinality.MANY && child.getNodeType().getKind() == TypeKind.ARRAY) {
-            type = ((ArrayType) child.getNodeType()).getComponentType();
-        } else {
-            type = child.getNodeType();
-        }
-        return type;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public NodeChildData getChild() {
-        return child;
-    }
-
-    public int getIndex() {
-        return index;
-    }
-
-    public boolean isIndexed() {
-        return index > -1;
-    }
-
-    public boolean isShortCircuit() {
-        return shortCircuit;
-    }
-
-    public String getShortCircuitId() {
-        return createShortCircuitId(child, index);
-    }
-
-    public static String createShortCircuitId(NodeChildData child, int varArgsIndex) {
-        String shortCircuitName = child.getName();
-        if (child.getCardinality().isMany()) {
-            shortCircuitName = shortCircuitName + "[" + varArgsIndex + "]";
-        }
-        return shortCircuitName;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeFieldData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class NodeFieldData extends MessageContainer {
-
-    private final Element messageElement;
-    private final AnnotationMirror messageAnnotation;
-    private final String name;
-    private final TypeMirror type;
-    private final boolean generated;
-    private ExecutableElement getter;
-
-    public NodeFieldData(Element messageElement, AnnotationMirror messageAnnotation, TypeMirror type, String name, boolean generated) {
-        this.messageElement = messageElement;
-        this.messageAnnotation = messageAnnotation;
-        this.name = name;
-        this.type = type;
-        this.generated = generated;
-    }
-
-    void setGetter(ExecutableElement getter) {
-        this.getter = getter;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return messageElement;
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return messageAnnotation;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public TypeMirror getType() {
-        return type;
-    }
-
-    public boolean isGenerated() {
-        return generated;
-    }
-
-    public ExecutableElement getGetter() {
-        return getter;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public abstract class NodeMethodParser<E extends TemplateMethod> extends TemplateMethodParser<NodeData, E> {
-
-    public NodeMethodParser(ProcessorContext context, NodeData node) {
-        super(context, node);
-    }
-
-    public NodeData getNode() {
-        return template;
-    }
-
-    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
-        ParameterSpec spec = new ParameterSpec(execution.getName(), nodeTypeMirrors(execution.getChild().getNodeData()));
-        spec.setExecution(execution);
-        return spec;
-    }
-
-    protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
-        Set<TypeMirror> typeMirrors = new LinkedHashSet<>();
-
-        for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) {
-            typeMirrors.add(typeData.getType().getPrimitiveType());
-        }
-
-        typeMirrors.add(nodeData.getTypeSystem().getGenericType());
-
-        return new ArrayList<>(typeMirrors);
-    }
-
-    protected ParameterSpec createReturnParameterSpec() {
-        ParameterSpec returnValue = new ParameterSpec("returnValue", nodeTypeMirrors(getNode()));
-        returnValue.setExecution(getNode().getThisExecution());
-        return returnValue;
-    }
-
-    @Override
-    public boolean isParsable(ExecutableElement method) {
-        if (getAnnotationType() != null) {
-            return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
-        }
-
-        return true;
-    }
-
-    @SuppressWarnings("unused")
-    protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, boolean shortCircuitsEnabled, String shortCircuitName) {
-        MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec());
-
-        addDefaultFrame(methodSpec);
-        addDefaultFieldMethodSpec(methodSpec);
-        addDefaultChildren(shortCircuitsEnabled, shortCircuitName, methodSpec);
-
-        return methodSpec;
-    }
-
-    public void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec spec) {
-        if (getNode().getChildren() == null) {
-            // children are null when parsing executable types
-            return;
-        }
-
-        for (NodeExecutionData execution : getNode().getChildExecutions()) {
-            if (breakName != null && execution.getShortCircuitId().equals(breakName)) {
-                break;
-            }
-
-            if (execution.isShortCircuit() && shortCircuitsEnabled) {
-                spec.addRequired(new ParameterSpec(shortCircuitValueName(execution.getName()), getContext().getType(boolean.class)));
-            }
-            spec.addRequired(createValueParameterSpec(execution));
-        }
-    }
-
-    private void addDefaultFrame(MethodSpec methodSpec) {
-        if (getNode().supportsFrame()) {
-            methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame()));
-        }
-    }
-
-    protected void addDefaultFieldMethodSpec(MethodSpec methodSpec) {
-        for (NodeFieldData field : getNode().getFields()) {
-            if (field.getGetter() == null) {
-                ParameterSpec spec = new ParameterSpec(field.getName(), field.getType());
-                spec.setLocal(true);
-                methodSpec.addOptional(spec);
-            }
-        }
-    }
-
-    private static String shortCircuitValueName(String valueName) {
-        return "has" + Utils.firstLetterUpperCase(valueName);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1351 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-import javax.tools.Diagnostic.Kind;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.compiler.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality;
-import com.oracle.truffle.dsl.processor.node.SpecializationData.SpecializationKind;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.template.TemplateMethod.TypeSignature;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class NodeParser extends AbstractParser<NodeData> {
-
-    public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class,
-                    NodeChildren.class);
-
-    private Map<String, NodeData> parsedNodes;
-
-    @Override
-    protected NodeData parse(Element element, AnnotationMirror mirror) {
-        NodeData node = null;
-        try {
-            parsedNodes = new HashMap<>();
-            node = resolveNode((TypeElement) element);
-            if (Log.DEBUG) {
-                NodeData parsed = parsedNodes.get(Utils.getQualifiedName((TypeElement) element));
-                if (node != null) {
-                    String dump = parsed.dump();
-                    log.message(Kind.ERROR, null, null, null, dump);
-                }
-            }
-        } finally {
-            parsedNodes = null;
-        }
-
-        return node;
-    }
-
-    @Override
-    protected NodeData filterErrorElements(NodeData model) {
-        for (Iterator<NodeData> iterator = model.getEnclosingNodes().iterator(); iterator.hasNext();) {
-            NodeData node = filterErrorElements(iterator.next());
-            if (node == null) {
-                iterator.remove();
-            }
-        }
-        if (model.hasErrors()) {
-            return null;
-        }
-        return model;
-    }
-
-    @Override
-    public boolean isDelegateToRootDeclaredType() {
-        return true;
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return null;
-    }
-
-    @Override
-    public List<Class<? extends Annotation>> getTypeDelegatedAnnotationTypes() {
-        return ANNOTATIONS;
-    }
-
-    private NodeData resolveNode(TypeElement rootType) {
-        String typeName = Utils.getQualifiedName(rootType);
-        if (parsedNodes.containsKey(typeName)) {
-            return parsedNodes.get(typeName);
-        }
-
-        List<NodeData> enclosedNodes = new ArrayList<>();
-        for (TypeElement enclosedType : ElementFilter.typesIn(rootType.getEnclosedElements())) {
-            NodeData enclosedChild = resolveNode(enclosedType);
-            if (enclosedChild != null) {
-                enclosedNodes.add(enclosedChild);
-            }
-        }
-
-        NodeData node = parseNode(rootType);
-        if (node == null && !enclosedNodes.isEmpty()) {
-            node = new NodeData(context, rootType);
-        }
-
-        if (node != null) {
-            for (NodeData enclosedNode : enclosedNodes) {
-                node.addEnclosedNode(enclosedNode);
-            }
-        }
-
-        parsedNodes.put(typeName, node);
-        return node;
-    }
-
-    private NodeData parseNode(TypeElement originalTemplateType) {
-        // reloading the type elements is needed for ecj
-        TypeElement templateType = Utils.fromTypeMirror(context.reloadTypeElement(originalTemplateType));
-
-        if (Utils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) {
-            // generated nodes should not get called again.
-            return null;
-        }
-
-        List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType);
-        if (!Utils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) {
-            return null;
-        }
-        List<? extends Element> elements = CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType);
-
-        NodeData node = parseNodeData(templateType, elements, lookupTypes);
-        if (node.hasErrors()) {
-            return node; // error sync point
-        }
-
-        initializeChildren(node);
-
-        node.getSpecializations().addAll(new SpecializationMethodParser(context, node).parse(elements));
-        node.getSpecializations().addAll(new GenericParser(context, node).parse(elements));
-        node.getCasts().addAll(new CreateCastParser(context, node).parse(elements));
-        node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(elements));
-
-        if (node.hasErrors()) {
-            return node;  // error sync point
-        }
-
-        verifySpecializationSameLength(node);
-        initializeSpecializations(elements, node);
-        initializeShortCircuits(node); // requires specializations and polymorphic specializations
-
-        verifyVisibilities(node);
-        verifyMissingAbstractMethods(node, elements);
-        verifyConstructors(node);
-        verifyNamingConvention(node.getShortCircuits(), "needs");
-        verifySpecializationThrows(node);
-        return node;
-    }
-
-    private NodeData parseNodeData(TypeElement templateType, List<? extends Element> elements, List<TypeElement> typeHierarchy) {
-        AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class);
-        if (typeSystemMirror == null) {
-            NodeData nodeData = new NodeData(context, templateType);
-            nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(templateType));
-            return nodeData;
-        }
-
-        TypeMirror typeSystemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value");
-        final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true);
-        if (typeSystem == null) {
-            NodeData nodeData = new NodeData(context, templateType);
-            nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSystemType));
-            return nodeData;
-        }
-
-        List<String> assumptionsList = new ArrayList<>();
-        for (int i = typeHierarchy.size() - 1; i >= 0; i--) {
-            TypeElement type = typeHierarchy.get(i);
-            AnnotationMirror assumptions = Utils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class);
-            if (assumptions != null) {
-                List<String> assumptionStrings = Utils.getAnnotationValueList(String.class, assumptions, "value");
-                for (String string : assumptionStrings) {
-                    if (assumptionsList.contains(string)) {
-                        assumptionsList.remove(string);
-                    }
-                    assumptionsList.add(string);
-                }
-            }
-        }
-        AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class);
-        String shortName = null;
-        if (nodeInfoMirror != null) {
-            shortName = Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName");
-        }
-
-        List<NodeFieldData> fields = parseFields(typeHierarchy, elements);
-        List<NodeChildData> children = parseChildren(typeHierarchy, elements);
-        List<NodeExecutionData> executions = parseExecutions(children, elements);
-
-        NodeData nodeData = new NodeData(context, templateType, shortName, typeSystem, children, executions, fields, assumptionsList);
-        nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
-
-        parsedNodes.put(Utils.getQualifiedName(templateType), nodeData);
-
-        return nodeData;
-    }
-
-    private List<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) {
-        Set<String> names = new HashSet<>();
-
-        List<NodeFieldData> fields = new ArrayList<>();
-        for (VariableElement field : ElementFilter.fieldsIn(elements)) {
-            if (field.getModifiers().contains(Modifier.STATIC)) {
-                continue;
-            }
-            if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) {
-                String name = field.getSimpleName().toString();
-                fields.add(new NodeFieldData(field, null, field.asType(), name, false));
-                names.add(name);
-            }
-        }
-
-        List<TypeElement> reversedTypeHierarchy = new ArrayList<>(typeHierarchy);
-        Collections.reverse(reversedTypeHierarchy);
-        for (TypeElement typeElement : reversedTypeHierarchy) {
-            AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, typeElement, NodeFields.class);
-            List<AnnotationMirror> children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", typeElement, NodeField.class);
-
-            for (AnnotationMirror mirror : children) {
-                String name = Utils.firstLetterLowerCase(Utils.getAnnotationValue(String.class, mirror, "name"));
-                TypeMirror type = Utils.getAnnotationValue(TypeMirror.class, mirror, "type");
-
-                NodeFieldData field = new NodeFieldData(typeElement, mirror, type, name, true);
-                if (name.isEmpty()) {
-                    field.addError(Utils.getAnnotationValue(mirror, "name"), "Field name cannot be empty.");
-                } else if (names.contains(name)) {
-                    field.addError(Utils.getAnnotationValue(mirror, "name"), "Duplicate field name '%s'.", name);
-                }
-                names.add(name);
-
-                fields.add(field);
-            }
-        }
-
-        for (NodeFieldData nodeFieldData : fields) {
-            nodeFieldData.setGetter(findGetter(elements, nodeFieldData.getName(), nodeFieldData.getType()));
-        }
-
-        return fields;
-    }
-
-    private List<NodeChildData> parseChildren(final List<TypeElement> typeHierarchy, List<? extends Element> elements) {
-        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.getAnnotationValue(String.class, mirror, "value"));
-            }
-        }
-        Map<String, TypeMirror> castNodeTypes = new HashMap<>();
-        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
-            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, CreateCast.class);
-            if (mirror != null) {
-                List<String> children = (Utils.getAnnotationValueList(String.class, mirror, "value"));
-                if (children != null) {
-                    for (String child : children) {
-                        castNodeTypes.put(child, method.getReturnType());
-                    }
-                }
-            }
-        }
-
-        List<NodeChildData> parsedChildren = new ArrayList<>();
-        List<TypeElement> typeHierarchyReversed = new ArrayList<>(typeHierarchy);
-        Collections.reverse(typeHierarchyReversed);
-        for (TypeElement type : typeHierarchyReversed) {
-            AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, type, NodeChildren.class);
-
-            TypeMirror nodeClassType = type.getSuperclass();
-            if (!Utils.isAssignable(nodeClassType, context.getTruffleTypes().getNode())) {
-                nodeClassType = null;
-            }
-
-            List<AnnotationMirror> children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class);
-            int index = 0;
-            for (AnnotationMirror childMirror : children) {
-                String name = Utils.getAnnotationValue(String.class, childMirror, "value");
-                if (name.equals("")) {
-                    name = "child" + index;
-                }
-
-                Cardinality cardinality = Cardinality.ONE;
-
-                TypeMirror childType = inheritType(childMirror, "type", nodeClassType);
-                if (childType.getKind() == TypeKind.ARRAY) {
-                    cardinality = Cardinality.MANY;
-                }
-
-                TypeMirror originalChildType = childType;
-                TypeMirror castNodeType = castNodeTypes.get(name);
-                if (castNodeType != null) {
-                    childType = castNodeType;
-                }
-
-                Element getter = findGetter(elements, name, childType);
-
-                NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality);
-
-                parsedChildren.add(nodeChild);
-
-                if (nodeChild.getNodeType() == null) {
-                    nodeChild.addError("No valid node type could be resoleved.");
-                }
-                if (nodeChild.hasErrors()) {
-                    continue;
-                }
-
-                index++;
-            }
-        }
-
-        List<NodeChildData> filteredChildren = new ArrayList<>();
-        Set<String> encounteredNames = new HashSet<>();
-        for (int i = parsedChildren.size() - 1; i >= 0; i--) {
-            NodeChildData child = parsedChildren.get(i);
-            if (!encounteredNames.contains(child.getName())) {
-                filteredChildren.add(0, child);
-                encounteredNames.add(child.getName());
-            }
-        }
-
-        for (NodeChildData child : filteredChildren) {
-            List<String> executeWithStrings = Utils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith");
-            AnnotationValue executeWithValue = Utils.getAnnotationValue(child.getMessageAnnotation(), "executeWith");
-            List<NodeChildData> executeWith = new ArrayList<>();
-            for (String executeWithString : executeWithStrings) {
-
-                if (child.getName().equals(executeWithString)) {
-                    child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString);
-                    continue;
-                }
-
-                NodeChildData found = null;
-                boolean before = true;
-                for (NodeChildData resolveChild : filteredChildren) {
-                    if (resolveChild == child) {
-                        before = false;
-                        continue;
-                    }
-                    if (resolveChild.getName().equals(executeWithString)) {
-                        found = resolveChild;
-                        break;
-                    }
-                }
-
-                if (found == null) {
-                    child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString);
-                    continue;
-                } else if (!before) {
-                    child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString,
-                                    executeWithString);
-                    continue;
-                }
-                executeWith.add(found);
-            }
-            child.setExecuteWith(executeWith);
-            if (child.getNodeData() == null) {
-                continue;
-            }
-        }
-
-        return filteredChildren;
-    }
-
-    private List<NodeExecutionData> parseExecutions(List<NodeChildData> children, List<? extends Element> elements) {
-        if (children == null) {
-            return null;
-        }
-
-        // pre-parse short circuits
-        Set<String> shortCircuits = new HashSet<>();
-        List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
-        for (ExecutableElement method : methods) {
-            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
-            if (mirror != null) {
-                shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value"));
-            }
-        }
-
-        boolean hasVarArgs = false;
-        int maxSignatureSize = 0;
-        if (!children.isEmpty()) {
-            int lastIndex = children.size() - 1;
-            hasVarArgs = children.get(lastIndex).getCardinality() == Cardinality.MANY;
-            if (hasVarArgs) {
-                maxSignatureSize = lastIndex;
-            } else {
-                maxSignatureSize = children.size();
-            }
-        }
-
-        // pre-parse specializations
-        for (ExecutableElement method : methods) {
-            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, Specialization.class);
-            if (mirror == null) {
-                continue;
-            }
-
-            int currentArgumentCount = 0;
-            boolean skipShortCircuit = false;
-            for (VariableElement var : method.getParameters()) {
-                TypeMirror type = var.asType();
-                if (currentArgumentCount == 0) {
-                    // skip optionals
-                    if (Utils.typeEquals(type, context.getTruffleTypes().getFrame())) {
-                        continue;
-                    }
-                    // TODO skip optional fields?
-                }
-                int childIndex = currentArgumentCount < children.size() ? currentArgumentCount : children.size() - 1;
-                if (childIndex == -1) {
-                    continue;
-                }
-                if (!skipShortCircuit) {
-                    NodeChildData child = children.get(childIndex);
-                    if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentCount - childIndex))) {
-                        skipShortCircuit = true;
-                        continue;
-                    }
-                } else {
-                    skipShortCircuit = false;
-                }
-
-                currentArgumentCount++;
-            }
-            maxSignatureSize = Math.max(maxSignatureSize, currentArgumentCount);
-        }
-
-        List<NodeExecutionData> executions = new ArrayList<>();
-        for (int i = 0; i < maxSignatureSize; i++) {
-            int childIndex = i;
-            boolean varArg = false;
-            if (childIndex >= children.size() - 1) {
-                if (hasVarArgs) {
-                    childIndex = children.size() - 1;
-                    varArg = hasVarArgs;
-                } else if (childIndex >= children.size()) {
-                    break;
-                }
-            }
-            int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1;
-            NodeChildData child = children.get(childIndex);
-            boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, varArgsIndex));
-            executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit));
-        }
-        return executions;
-    }
-
-    private static Map<Integer, List<ExecutableTypeData>> groupExecutableTypes(List<ExecutableTypeData> executableTypes) {
-        Map<Integer, List<ExecutableTypeData>> groupedTypes = new TreeMap<>();
-        for (ExecutableTypeData type : executableTypes) {
-            int evaluatedCount = type.getEvaluatedCount();
-
-            List<ExecutableTypeData> types = groupedTypes.get(evaluatedCount);
-            if (types == null) {
-                types = new ArrayList<>();
-                groupedTypes.put(evaluatedCount, types);
-            }
-            types.add(type);
-        }
-
-        for (List<ExecutableTypeData> types : groupedTypes.values()) {
-            Collections.sort(types);
-        }
-        return groupedTypes;
-    }
-
-    private void initializeChildren(NodeData node) {
-        for (NodeChildData nodeChild : node.getChildren()) {
-            NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(nodeChild.getNodeType()));
-            nodeChild.setNode(fieldNodeData);
-            if (fieldNodeData == null) {
-                nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(nodeChild.getNodeType()));
-            } else if (!Utils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) {
-                nodeChild.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(),
-                                NodeChild.class.getSimpleName(), Utils.getSimpleName(node.getTypeSystem().getTemplateType()), Utils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType()));
-            }
-            if (fieldNodeData != null) {
-                List<ExecutableTypeData> types = nodeChild.findGenericExecutableTypes(context);
-                if (types.isEmpty()) {
-                    AnnotationValue executeWithValue = Utils.getAnnotationValue(nodeChild.getMessageAnnotation(), "executeWith");
-                    nodeChild.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", nodeChild.getExecuteWith().size(),
-                                    Utils.getSimpleName(nodeChild.getNodeType()));
-                }
-            }
-        }
-    }
-
-    private void initializeSpecializations(List<? extends Element> elements, final NodeData node) {
-        if (node.getSpecializations().isEmpty()) {
-            return;
-        }
-
-        initializeGuards(elements, node);
-        initializeGeneric(node);
-        initializeUninitialized(node);
-        initializeOrder(node);
-        initializePolymorphism(node); // requires specializations
-        initializeReachability(node);
-        initializeContains(node);
-
-        if (!node.hasErrors()) {
-            initializeExceptions(node);
-        }
-        resolveContains(node);
-
-        List<SpecializationData> needsId = new ArrayList<>();
-        for (SpecializationData specialization : node.getSpecializations()) {
-            if (specialization.isGeneric()) {
-                specialization.setId("Generic");
-            } else if (specialization.isUninitialized()) {
-                specialization.setId("Uninitialized");
-            } else if (specialization.isPolymorphic()) {
-                specialization.setId("Polymorphic");
-            } else if (specialization.isSpecialized()) {
-                needsId.add(specialization);
-            } else {
-                throw new AssertionError();
-            }
-        }
-
-        // verify specialization parameter length
-        List<String> ids = initializeSpecializationIds(needsId);
-        for (int i = 0; i < ids.size(); i++) {
-            needsId.get(i).setId(ids.get(i));
-        }
-
-    }
-
-    private static void initializeOrder(NodeData node) {
-        List<SpecializationData> specializations = node.getSpecializations();
-        Collections.sort(specializations);
-
-        for (SpecializationData specialization : specializations) {
-            String searchName = specialization.getInsertBeforeName();
-            if (searchName == null || specialization.getMethod() == null) {
-                continue;
-            }
-            SpecializationData found = lookupSpecialization(node, searchName);
-            if (found == null || found.getMethod() == null) {
-                AnnotationValue value = Utils.getAnnotationValue(specialization.getMarkerAnnotation(), "insertBefore");
-                specialization.addError(value, "The referenced specialization '%s' could not be found.", searchName);
-                continue;
-            }
-
-            ExecutableElement currentMethod = specialization.getMethod();
-            ExecutableElement insertBeforeMethod = found.getMethod();
-
-            TypeMirror currentEnclosedType = currentMethod.getEnclosingElement().asType();
-            TypeMirror insertBeforeEnclosedType = insertBeforeMethod.getEnclosingElement().asType();
-
-            if (Utils.typeEquals(currentEnclosedType, insertBeforeEnclosedType) || !Utils.isSubtype(currentEnclosedType, insertBeforeEnclosedType)) {
-                AnnotationValue value = Utils.getAnnotationValue(specialization.getMarkerAnnotation(), "insertBefore");
-                specialization.addError(value, "Specializations can only be inserted before specializations in superclasses.", searchName);
-                continue;
-            }
-
-            specialization.setInsertBefore(found);
-        }
-
-        int endIndex = specializations.size() - 1;
-        for (int i = endIndex; i >= 0; i--) {
-            SpecializationData specialization = specializations.get(i);
-            if (specialization.isGeneric() || specialization.isPolymorphic()) {
-                endIndex--;
-                continue;
-            }
-
-            SpecializationData insertBefore = specialization.getInsertBefore();
-            if (insertBefore != null) {
-                int insertIndex = specializations.indexOf(insertBefore);
-                if (insertIndex < i) {
-                    List<SpecializationData> range = new ArrayList<>(specializations.subList(i, endIndex + 1));
-                    specializations.removeAll(range);
-                    specializations.addAll(insertIndex, range);
-                }
-            }
-        }
-
-        for (int i = 0; i < specializations.size(); i++) {
-            specializations.get(i).setIndex(i);
-        }
-    }
-
-    private static void initializeExceptions(NodeData node) {
-        List<SpecializationData> specializations = node.getSpecializations();
-        for (int i = 0; i < specializations.size(); i++) {
-            SpecializationData cur = specializations.get(i);
-            if (cur.getExceptions().isEmpty()) {
-                continue;
-            }
-            SpecializationData next = i + 1 < specializations.size() ? specializations.get(i + 1) : null;
-
-            if (!cur.isContainedBy(next)) {
-                // error should be able to contain
-                next.addError("This specialiation is not a valid exceptional rewrite target for %s. To fix this make %s compatible to %s or remove the exceptional rewrite.",
-                                cur.createReferenceName(), next.createReferenceName(), cur.createReferenceName());
-                continue;
-            }
-            if (!next.getContains().contains(cur)) {
-                next.getContains().add(cur);
-                // TODO resolve transitive contains
-            }
-        }
-
-        for (SpecializationData cur : specializations) {
-            if (cur.getExceptions().isEmpty()) {
-                continue;
-            }
-            for (SpecializationData child : specializations) {
-                if (child != null && child != cur && child.getContains().contains(cur)) {
-                    cur.getExcludedBy().add(child);
-                }
-            }
-        }
-    }
-
-    private static void initializeContains(NodeData node) {
-        for (SpecializationData specialization : node.getSpecializations()) {
-            Set<SpecializationData> resolvedSpecializations = specialization.getContains();
-            resolvedSpecializations.clear();
-            Set<String> includeNames = specialization.getContainsNames();
-            for (String includeName : includeNames) {
-                // TODO reduce complexity of this lookup.
-                SpecializationData foundSpecialization = lookupSpecialization(node, includeName);
-
-                if (foundSpecialization == null) {
-                    AnnotationValue value = Utils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
-                    specialization.addError(value, "The referenced specialization '%s' could not be found.", includeName);
-                } else {
-                    if (!foundSpecialization.isContainedBy(specialization)) {
-                        AnnotationValue value = Utils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
-                        if (foundSpecialization.compareTo(specialization) > 0) {
-                            specialization.addError(value, "The contained specialization '%s' must be declared before the containing specialization.", includeName);
-                        } else {
-                            specialization.addError(value,
-                                            "The contained specialization '%s' is not fully compatible. The contained specialization must be strictly more generic than the containing one.",
-                                            includeName);
-                        }
-
-                    }
-                    resolvedSpecializations.add(foundSpecialization);
-                }
-            }
-        }
-    }
-
-    private void resolveContains(NodeData node) {
-        // flatten transitive includes
-        for (SpecializationData specialization : node.getSpecializations()) {
-            if (specialization.getContains().isEmpty()) {
-                continue;
-            }
-            Set<SpecializationData> foundSpecializations = new HashSet<>();
-            collectIncludes(specialization, foundSpecializations, new HashSet<SpecializationData>());
-            specialization.getContains().addAll(foundSpecializations);
-        }
-    }
-
-    private static SpecializationData lookupSpecialization(NodeData node, String includeName) {
-        SpecializationData foundSpecialization = null;
-        for (SpecializationData searchSpecialization : node.getSpecializations()) {
-            if (searchSpecialization.getMethodName().equals(includeName)) {
-                foundSpecialization = searchSpecialization;
-                break;
-            }
-        }
-        return foundSpecialization;
-    }
-
-    private void collectIncludes(SpecializationData specialization, Set<SpecializationData> found, Set<SpecializationData> visited) {
-        if (visited.contains(specialization)) {
-            // circle found
-            specialization.addError("Circular contained specialization '%s' found.", specialization.createReferenceName());
-            return;
-        }
-        visited.add(specialization);
-
-        for (SpecializationData included : specialization.getContains()) {
-            collectIncludes(included, found, new HashSet<>(visited));
-            found.add(included);
-        }
-    }
-
-    private static void initializeReachability(final NodeData node) {
-        List<SpecializationData> specializations = node.getSpecializations();
-        for (int i = specializations.size() - 1; i >= 0; i--) {
-            SpecializationData current = specializations.get(i);
-            if (current.isPolymorphic()) {
-                current.setReachable(true);
-                continue;
-            }
-
-            List<SpecializationData> shadowedBy = null;
-            for (int j = i - 1; j >= 0; j--) {
-                SpecializationData prev = specializations.get(j);
-                if (prev.isPolymorphic()) {
-                    continue;
-                }
-                if (!current.isReachableAfter(prev)) {
-                    if (shadowedBy == null) {
-                        shadowedBy = new ArrayList<>();
-                    }
-                    shadowedBy.add(prev);
-                }
-            }
-
-            if (shadowedBy != null) {
-                StringBuilder name = new StringBuilder();
-                String sep = "";
-                for (SpecializationData shadowSpecialization : shadowedBy) {
-                    name.append(sep);
-                    name.append(shadowSpecialization.createReferenceName());
-                    sep = ", ";
-                }
-                current.addError("%s is not reachable. It is shadowed by %s.", current.isGeneric() ? "Generic" : "Specialization", name);
-            }
-            current.setReachable(shadowedBy == null);
-        }
-    }
-
-    private static List<String> initializeSpecializationIds(List<SpecializationData> specializations) {
-        int lastSize = -1;
-        List<List<String>> signatureChunks = new ArrayList<>();
-        for (SpecializationData other : specializations) {
-            if (!other.isSpecialized()) {
-                continue;
-            }
-            List<String> paramIds = new LinkedList<>();
-            paramIds.add(Utils.getTypeId(other.getReturnType().getType()));
-            for (ActualParameter param : other.getParameters()) {
-                if (param.getSpecification().getExecution() == null) {
-                    continue;
-                }
-                paramIds.add(Utils.getTypeId(param.getType()));
-            }
-            assert lastSize == -1 || lastSize == paramIds.size();
-            if (lastSize != -1 && lastSize != paramIds.size()) {
-                throw new AssertionError();
-            }
-            signatureChunks.add(paramIds);
-            lastSize = paramIds.size();
-        }
-
-        // reduce id vertically
-        for (int i = 0; i < lastSize; i++) {
-            String prev = null;
-            boolean allSame = true;
-            for (List<String> signature : signatureChunks) {
-                String arg = signature.get(i);
-                if (prev == null) {
-                    prev = arg;
-                    continue;
-                } else if (!prev.equals(arg)) {
-                    allSame = false;
-                    break;
-                }
-                prev = arg;
-            }
-
-            if (allSame) {
-                for (List<String> signature : signatureChunks) {
-                    signature.remove(i);
-                }
-                lastSize--;
-            }
-        }
-
-        // reduce id horizontally
-        for (List<String> signature : signatureChunks) {
-            if (signature.isEmpty()) {
-                continue;
-            }
-            String prev = null;
-            boolean allSame = true;
-            for (String arg : signature) {
-                if (prev == null) {
-                    prev = arg;
-                    continue;
-                } else if (!prev.equals(arg)) {
-                    allSame = false;
-                    break;
-                }
-                prev = arg;
-            }
-
-            if (allSame) {
-                signature.clear();
-                signature.add(prev);
-            }
-        }
-
-        // create signatures
-        List<String> signatures = new ArrayList<>();
-        for (List<String> signatureChunk : signatureChunks) {
-            StringBuilder b = new StringBuilder();
-            if (signatureChunk.isEmpty()) {
-                b.append("Default");
-            } else {
-                for (String s : signatureChunk) {
-                    b.append(s);
-                }
-            }
-            signatures.add(b.toString());
-        }
-
-        Map<String, Integer> counts = new HashMap<>();
-        for (String s1 : signatures) {
-            Integer count = counts.get(s1);
-            if (count == null) {
-                count = 0;
-            }
-            count++;
-            counts.put(s1, count);
-        }
-
-        for (String s : counts.keySet()) {
-            int count = counts.get(s);
-            if (count > 1) {
-                int number = 0;
-                for (ListIterator<String> iterator = signatures.listIterator(); iterator.hasNext();) {
-                    String s2 = iterator.next();
-                    if (s.equals(s2)) {
-                        iterator.set(s2 + number);
-                        number++;
-                    }
-                }
-            }
-        }
-
-        return signatures;
-    }
-
-    private void initializeGuards(List<? extends Element> elements, NodeData node) {
-        Map<String, List<GuardData>> guards = new HashMap<>();
-        for (SpecializationData specialization : node.getSpecializations()) {
-            for (GuardExpression exp : specialization.getGuards()) {
-                guards.put(exp.getGuardName(), null);
-            }
-        }
-
-        GuardParser parser = new GuardParser(context, node, null, guards.keySet());
-        List<GuardData> resolvedGuards = parser.parse(elements);
-        for (GuardData guard : resolvedGuards) {
-            List<GuardData> groupedGuards = guards.get(guard.getMethodName());
-            if (groupedGuards == null) {
-                groupedGuards = new ArrayList<>();
-                guards.put(guard.getMethodName(), groupedGuards);
-            }
-            groupedGuards.add(guard);
-        }
-
-        for (SpecializationData specialization : node.getSpecializations()) {
-            for (GuardExpression exp : specialization.getGuards()) {
-                resolveGuardExpression(node, specialization, guards, exp);
-            }
-        }
-    }
-
-    private void resolveGuardExpression(NodeData node, TemplateMethod source, Map<String, List<GuardData>> guards, GuardExpression expression) {
-        List<GuardData> availableGuards = guards.get(expression.getGuardName());
-        if (availableGuards == null) {
-            source.addError("No compatible guard with method name '%s' found. Please note that all signature types of the method guard must be declared in the type system.", expression.getGuardName());
-            return;
-        }
-        List<ExecutableElement> guardMethods = new ArrayList<>();
-        for (GuardData guard : availableGuards) {
-            guardMethods.add(guard.getMethod());
-        }
-        GuardParser parser = new GuardParser(context, node, source, new HashSet<>(Arrays.asList(expression.getGuardName())));
-        List<GuardData> matchingGuards = parser.parse(guardMethods);
-        if (!matchingGuards.isEmpty()) {
-            GuardData guard = matchingGuards.get(0);
-            // use the shared instance of the guard data
-            for (GuardData guardData : availableGuards) {
-                if (guardData.getMethod() == guard.getMethod()) {
-                    expression.setGuard(guardData);
-                    return;
-                }
-            }
-            throw new AssertionError("Should not reach here.");
-        } else {
-            MethodSpec spec = parser.createSpecification(source.getMethod(), source.getMarkerAnnotation());
-            spec.applyTypeDefinitions("types");
-            source.addError("No guard with name '%s' matched the required signature. Expected signature: %n%s", expression.getGuardName(), spec.toSignatureString("guard"));
-        }
-    }
-
-    private void initializeGeneric(final NodeData node) {
-        if (!node.needsRewrites(context)) {
-            return;
-        }
-
-        List<SpecializationData> generics = new ArrayList<>();
-        for (SpecializationData spec : node.getSpecializations()) {
-            if (spec.isGeneric()) {
-                generics.add(spec);
-            }
-        }
-
-        if (generics.size() == 1 && node.getSpecializations().size() == 1) {
-            // TODO this limitation should be lifted
-            for (SpecializationData generic : generics) {
-                generic.addError("@%s defined but no @%s.", Generic.class.getSimpleName(), Specialization.class.getSimpleName());
-            }
-        }
-
-        if (generics.isEmpty()) {
-            node.getSpecializations().add(createGenericSpecialization(node));
-        } else {
-            if (generics.size() > 1) {
-                for (SpecializationData generic : generics) {
-                    generic.addError("Only @%s is allowed per operation.", Generic.class.getSimpleName());
-                }
-            }
-        }
-    }
-
-    private SpecializationData createGenericSpecialization(final NodeData node) {
-        GenericParser parser = new GenericParser(context, node);
-        MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null);
-
-        List<TypeMirror> parameterTypes = new ArrayList<>();
-        int signatureIndex = 1;
-        for (ParameterSpec spec : specification.getRequired()) {
-            parameterTypes.add(createGenericType(spec, node.getSpecializations(), signatureIndex));
-            if (spec.isSignature()) {
-                signatureIndex++;
-            }
-        }
-
-        TypeMirror returnType = createGenericType(specification.getReturnType(), node.getSpecializations(), 0);
-        SpecializationData generic = parser.create("Generic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, parameterTypes);
-        if (generic == null) {
-            throw new RuntimeException("Unable to create generic signature for node " + node.getNodeId() + " with " + parameterTypes + ". Specification " + specification + ".");
-        }
-
-        return generic;
-    }
-
-    private TypeMirror createGenericType(ParameterSpec spec, List<SpecializationData> specializations, int signatureIndex) {
-        NodeExecutionData execution = spec.getExecution();
-        if (execution == null) {
-            if (spec.getAllowedTypes().size() == 1) {
-                return spec.getAllowedTypes().get(0);
-            } else {
-                return Utils.getCommonSuperType(context, spec.getAllowedTypes().toArray(new TypeMirror[0]));
-            }
-        } else {
-            Set<TypeData> types = new HashSet<>();
-            for (SpecializationData specialization : specializations) {
-                types.add(specialization.getTypeSignature().get(signatureIndex));
-            }
-
-            NodeChildData child = execution.getChild();
-            TypeData genericType = null;
-            if (types.size() == 1) {
-                ExecutableTypeData executable = child.findExecutableType(context, types.iterator().next());
-                if (executable != null && (signatureIndex == 0 || !executable.hasUnexpectedValue(context))) {
-                    genericType = types.iterator().next();
-                }
-            }
-            if (genericType == null) {
-                genericType = child.findAnyGenericExecutableType(context).getType();
-            }
-            return genericType.getPrimitiveType();
-        }
-    }
-
-    private static void initializeUninitialized(final NodeData node) {
-        SpecializationData generic = node.getGenericSpecialization();
-        if (generic == null) {
-            return;
-        }
-        for (ActualParameter parameter : generic.getReturnTypeAndParameters()) {
-            if (Utils.isObject(parameter.getType())) {
-                continue;
-            }
-            Set<String> types = new HashSet<>();
-            for (SpecializationData specialization : node.getSpecializations()) {
-                ActualParameter actualParameter = specialization.findParameter(parameter.getLocalName());
-                if (actualParameter != null) {
-                    types.add(Utils.getQualifiedName(actualParameter.getType()));
-                }
-            }
-            if (types.size() > 1) {
-                generic.replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, node.getTypeSystem().getGenericTypeData()));
-            }
-        }
-        TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", -1, node, generic.getSpecification(), null, null, generic.getReturnType(), generic.getParameters());
-        // should not use messages from generic specialization
-        uninializedMethod.getMessages().clear();
-        node.getSpecializations().add(new SpecializationData(node, uninializedMethod, SpecializationKind.UNINITIALIZED));
-    }
-
-    private void initializePolymorphism(NodeData node) {
-        if (!node.needsRewrites(context)) {
-            return;
-        }
-
-        SpecializationData generic = node.getGenericSpecialization();
-
-        List<TypeData> polymorphicSignature = new ArrayList<>();
-        List<ActualParameter> updatePolymorphic = Arrays.asList();
-        for (ActualParameter genericParameter : updatePolymorphic) {
-            if (!genericParameter.getSpecification().isSignature()) {
-                continue;
-            }
-
-            Set<TypeData> usedTypes = new HashSet<>();
-            for (SpecializationData specialization : node.getSpecializations()) {
-                if (!specialization.isSpecialized()) {
-                    continue;
-                }
-                ActualParameter parameter = specialization.findParameter(genericParameter.getLocalName());
-                if (parameter == null) {
-                    throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName());
-                }
-                usedTypes.add(parameter.getTypeSystemType());
-            }
-
-            TypeData polymorphicType;
-            if (usedTypes.size() == 1) {
-                polymorphicType = usedTypes.iterator().next();
-            } else {
-                polymorphicType = node.getTypeSystem().getGenericTypeData();
-            }
-            polymorphicSignature.add(polymorphicType);
-        }
-
-        SpecializationData polymorphic = new SpecializationData(node, generic, SpecializationKind.POLYMORPHIC);
-        polymorphic.updateSignature(new TypeSignature(polymorphicSignature));
-        node.getSpecializations().add(polymorphic);
-    }
-
-    private void initializeShortCircuits(NodeData node) {
-        Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
-
-        boolean valid = true;
-        List<NodeExecutionData> shortCircuitExecutions = new ArrayList<>();
-        for (NodeExecutionData execution : node.getChildExecutions()) {
-            if (!execution.isShortCircuit()) {
-                continue;
-            }
-            shortCircuitExecutions.add(execution);
-            String valueName = execution.getShortCircuitId();
-            List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
-
-            if (availableCircuits == null || availableCircuits.isEmpty()) {
-                node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
-                valid = false;
-                continue;
-            }
-
-            boolean sameMethodName = true;
-            String methodName = availableCircuits.get(0).getMethodName();
-            for (ShortCircuitData circuit : availableCircuits) {
-                if (!circuit.getMethodName().equals(methodName)) {
-                    sameMethodName = false;
-                }
-            }
-
-            if (!sameMethodName) {
-                for (ShortCircuitData circuit : availableCircuits) {
-                    circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName);
-                }
-                valid = false;
-                continue;
-            }
-
-            ShortCircuitData genericCircuit = null;
-            for (ShortCircuitData circuit : availableCircuits) {
-                if (isGenericShortCutMethod(circuit)) {
-                    genericCircuit = circuit;
-                    break;
-                }
-            }
-
-            if (genericCircuit == null) {
-                node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
-                valid = false;
-                continue;
-            }
-
-            for (ShortCircuitData circuit : availableCircuits) {
-                if (circuit != genericCircuit) {
-                    circuit.setGenericShortCircuitMethod(genericCircuit);
-                }
-            }
-        }
-
-        if (!valid) {
-            return;
-        }
-
-        List<SpecializationData> specializations = new ArrayList<>();
-        specializations.addAll(node.getSpecializations());
-        for (SpecializationData specialization : specializations) {
-            List<ShortCircuitData> assignedShortCuts = new ArrayList<>(shortCircuitExecutions.size());
-
-            for (NodeExecutionData shortCircuit : shortCircuitExecutions) {
-                List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(shortCircuit.getShortCircuitId());
-
-                ShortCircuitData genericShortCircuit = null;
-                ShortCircuitData compatibleShortCircuit = null;
-                for (ShortCircuitData circuit : availableShortCuts) {
-                    if (circuit.isGeneric()) {
-                        genericShortCircuit = circuit;
-                    } else if (circuit.isCompatibleTo(specialization)) {
-                        compatibleShortCircuit = circuit;
-                    }
-                }
-
-                if (compatibleShortCircuit == null) {
-                    compatibleShortCircuit = genericShortCircuit;
-                }
-                assignedShortCuts.add(compatibleShortCircuit);
-            }
-            specialization.setShortCircuits(assignedShortCuts);
-        }
-    }
-
-    private boolean isGenericShortCutMethod(ShortCircuitData method) {
-        for (ActualParameter parameter : method.getParameters()) {
-            NodeExecutionData execution = parameter.getSpecification().getExecution();
-            if (execution == null) {
-                continue;
-            }
-            ExecutableTypeData found = null;
-            List<ExecutableTypeData> executableElements = execution.getChild().findGenericExecutableTypes(context);
-            for (ExecutableTypeData executable : executableElements) {
-                if (executable.getType().equalsType(parameter.getTypeSystemType())) {
-                    found = executable;
-                    break;
-                }
-            }
-            if (found == null) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private static Map<String, List<ShortCircuitData>> groupShortCircuits(List<ShortCircuitData> shortCircuits) {
-        Map<String, List<ShortCircuitData>> group = new HashMap<>();
-        for (ShortCircuitData shortCircuit : shortCircuits) {
-            List<ShortCircuitData> circuits = group.get(shortCircuit.getValueName());
-            if (circuits == null) {
-                circuits = new ArrayList<>();
-                group.put(shortCircuit.getValueName(), circuits);
-            }
-            circuits.add(shortCircuit);
-        }
-        return group;
-    }
-
-    private static boolean verifySpecializationSameLength(NodeData nodeData) {
-        int lastArgs = -1;
-        for (SpecializationData specializationData : nodeData.getSpecializations()) {
-            int signatureArgs = specializationData.getSignatureSize();
-            if (lastArgs == signatureArgs) {
-                continue;
-            }
-            if (lastArgs != -1) {
-                for (SpecializationData specialization : nodeData.getSpecializations()) {
-                    specialization.addError("All specializations must have the same number of arguments.");
-                }
-                return false;
-            } else {
-                lastArgs = signatureArgs;
-            }
-        }
-        return true;
-    }
-
-    private static void verifyVisibilities(NodeData node) {
-        if (node.getTemplateType().getModifiers().contains(Modifier.PRIVATE) && node.getSpecializations().size() > 0) {
-            node.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName());
-        }
-    }
-
-    private static void verifyMissingAbstractMethods(NodeData nodeData, List<? extends Element> originalElements) {
-        if (!nodeData.needsFactory()) {
-            // missing abstract methods only needs to be implemented
-            // if we need go generate factory for it.
-            return;
-        }
-
-        List<Element> elements = new ArrayList<>(originalElements);
-        Set<Element> unusedElements = new HashSet<>(elements);
-        for (TemplateMethod method : nodeData.getAllTemplateMethods()) {
-            unusedElements.remove(method.getMethod());
-        }
-
-        for (NodeFieldData field : nodeData.getFields()) {
-            if (field.getGetter() != null) {
-                unusedElements.remove(field.getGetter());
-            }
-        }
-
-        for (NodeChildData child : nodeData.getChildren()) {
-            if (child.getAccessElement() != null) {
-                unusedElements.remove(child.getAccessElement());
-            }
-        }
-
-        for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) {
-            if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) {
-                nodeData.addError("The type %s must implement the inherited abstract method %s.", Utils.getSimpleName(nodeData.getTemplateType()), Utils.getReadableSignature(unusedMethod));
-            }
-        }
-    }
-
-    private static void verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) {
-        for (int i = 0; i < methods.size(); i++) {
-            TemplateMethod m1 = methods.get(i);
-            if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
-                m1.addError("Naming convention: method name must start with '%s'.", prefix);
-            }
-        }
-    }
-
-    private static void verifySpecializationThrows(NodeData node) {
-        Map<String, SpecializationData> specializationMap = new HashMap<>();
-        for (SpecializationData spec : node.getSpecializations()) {
-            specializationMap.put(spec.getMethodName(), spec);
-        }
-        for (SpecializationData sourceSpecialization : node.getSpecializations()) {
-            if (sourceSpecialization.getExceptions() != null) {
-                for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) {
-                    for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) {
-                        if (otherThrowsData != throwsData && Utils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) {
-                            throwsData.addError("Duplicate exception type.");
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private void verifyConstructors(NodeData nodeData) {
-        if (!nodeData.needsRewrites(context)) {
-            // no specialization constructor is needed if the node never rewrites.
-            return;
-        }
-
-        TypeElement type = Utils.fromTypeMirror(nodeData.getNodeType());
-        List<ExecutableElement> constructors = ElementFilter.constructorsIn(type.getEnclosedElements());
-
-        boolean parametersFound = false;
-        for (ExecutableElement constructor : constructors) {
-            if (!constructor.getParameters().isEmpty() && !isSourceSectionConstructor(context, constructor)) {
-                parametersFound = true;
-            }
-        }
-        if (!parametersFound) {
-            return;
-        }
-        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)) {
-                        nodeData.addError("The specialization constructor must not be private.");
-                    } else if (constructors.size() <= 1) {
-                        nodeData.addError("The specialization constructor must not be the only constructor. The definition of an alternative constructor is required.");
-                    }
-                    return;
-                }
-            }
-        }
-
-        // not found
-        nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type));
-    }
-
-    static boolean isSourceSectionConstructor(ProcessorContext context, ExecutableElement constructor) {
-        return constructor.getParameters().size() == 1 && Utils.typeEquals(constructor.getParameters().get(0).asType(), context.getTruffleTypes().getSourceSection());
-    }
-
-    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 TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) {
-        TypeMirror inhertNodeType = context.getTruffleTypes().getNode();
-        TypeMirror value = Utils.getAnnotationValue(TypeMirror.class, annotation, valueName);
-        if (Utils.typeEquals(inhertNodeType, value)) {
-            return parentType;
-        } else {
-            return value;
-        }
-    }
-
-    private ExecutableElement findGetter(List<? extends Element> elements, String variableName, TypeMirror type) {
-        if (type == null) {
-            return null;
-        }
-        String methodName;
-        if (Utils.typeEquals(type, context.getType(boolean.class))) {
-            methodName = "is" + Utils.firstLetterUpperCase(variableName);
-        } else {
-            methodName = "get" + Utils.firstLetterUpperCase(variableName);
-        }
-
-        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
-            if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.isAssignable(type, method.getReturnType())) {
-                return method;
-            }
-        }
-        return null;
-    }
-
-    private static List<TypeElement> collectSuperClasses(List<TypeElement> collection, TypeElement element) {
-        if (element != null) {
-            collection.add(element);
-            if (element.getSuperclass() != null) {
-                collectSuperClasses(collection, Utils.fromTypeMirror(element.getSuperclass()));
-            }
-        }
-        return collection;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /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.dsl.processor.node;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.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()) {
-            ActualParameter specializationParam = specialization.findParameter(param.getLocalName());
-            if (!Utils.typeEquals(param.getType(), specializationParam.getType())) {
-                return false;
-            }
-        }
-        return true;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java	Mon Aug 11 15:53:05 2014 +0200
+++ /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.dsl.processor.node;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class ShortCircuitParser extends NodeMethodParser<ShortCircuitData> {
-
-    private final Set<String> shortCircuitValues;
-
-    public ShortCircuitParser(ProcessorContext context, NodeData node) {
-        super(context, node);
-
-        shortCircuitValues = new HashSet<>();
-        for (NodeExecutionData execution : node.getChildExecutions()) {
-            if (execution.isShortCircuit()) {
-                shortCircuitValues.add(execution.getShortCircuitId());
-            }
-        }
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        String shortCircuitValue = Utils.getAnnotationValue(String.class, mirror, "value");
-
-        return createDefaultMethodSpec(method, mirror, true, shortCircuitValue);
-    }
-
-    @Override
-    protected ParameterSpec createReturnParameterSpec() {
-        return new ParameterSpec("has", getContext().getType(boolean.class));
-    }
-
-    @Override
-    public ShortCircuitData create(TemplateMethod method, boolean invalid) {
-        String shortCircuitValue = Utils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value");
-
-        if (!shortCircuitValues.contains(shortCircuitValue)) {
-            method.addError("Invalid short circuit value %s.", shortCircuitValue);
-        }
-
-        return new ShortCircuitData(method, shortCircuitValue);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return ShortCircuit.class;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,496 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.util.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public final class SpecializationData extends TemplateMethod {
-
-    public enum SpecializationKind {
-        UNINITIALIZED,
-        SPECIALIZED,
-        POLYMORPHIC,
-        GENERIC
-    }
-
-    private final NodeData node;
-    private final SpecializationKind kind;
-    private final List<SpecializationThrowsData> exceptions;
-    private List<GuardExpression> guards = Collections.emptyList();
-    private List<ShortCircuitData> shortCircuits;
-    private List<String> assumptions = Collections.emptyList();
-    private final Set<SpecializationData> contains = new TreeSet<>();
-    private final Set<String> containsNames = new TreeSet<>();
-    private final Set<SpecializationData> excludedBy = new TreeSet<>();
-    private String insertBeforeName;
-    private SpecializationData insertBefore;
-    private boolean reachable;
-    private int index;
-
-    public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind, List<SpecializationThrowsData> exceptions) {
-        super(template);
-        this.node = node;
-        this.kind = kind;
-        this.exceptions = exceptions;
-        this.index = template.getNaturalOrder();
-
-        for (SpecializationThrowsData exception : exceptions) {
-            exception.setSpecialization(this);
-        }
-    }
-
-    public void setInsertBefore(SpecializationData insertBefore) {
-        this.insertBefore = insertBefore;
-    }
-
-    public void setInsertBeforeName(String insertBeforeName) {
-        this.insertBeforeName = insertBeforeName;
-    }
-
-    public SpecializationData getInsertBefore() {
-        return insertBefore;
-    }
-
-    public String getInsertBeforeName() {
-        return insertBeforeName;
-    }
-
-    public Set<String> getContainsNames() {
-        return containsNames;
-    }
-
-    public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind) {
-        this(node, template, kind, new ArrayList<SpecializationThrowsData>());
-    }
-
-    public Set<SpecializationData> getContains() {
-        return contains;
-    }
-
-    public Set<SpecializationData> getExcludedBy() {
-        return excludedBy;
-    }
-
-    public void setReachable(boolean reachable) {
-        this.reachable = reachable;
-    }
-
-    public boolean isReachable() {
-        return reachable;
-    }
-
-    public boolean isPolymorphic() {
-        return kind == SpecializationKind.POLYMORPHIC;
-    }
-
-    @Override
-    protected List<MessageContainer> findChildContainers() {
-        List<MessageContainer> sinks = new ArrayList<>();
-        if (exceptions != null) {
-            sinks.addAll(exceptions);
-        }
-        if (guards != null) {
-            for (GuardExpression guard : guards) {
-                if (guard.isResolved()) {
-                    sinks.add(guard.getResolvedGuard());
-                }
-            }
-        }
-        return sinks;
-    }
-
-    public boolean hasRewrite(ProcessorContext context) {
-        if (!getExceptions().isEmpty()) {
-            return true;
-        }
-        if (!getGuards().isEmpty()) {
-            return true;
-        }
-        if (!getAssumptions().isEmpty()) {
-            return true;
-        }
-        for (ActualParameter parameter : getSignatureParameters()) {
-            ExecutableTypeData type = parameter.getSpecification().getExecution().getChild().findExecutableType(context, parameter.getTypeSystemType());
-            if (type.hasUnexpectedValue(context)) {
-                return true;
-            }
-            if (type.getReturnType().getTypeSystemType().needsCastTo(parameter.getTypeSystemType())) {
-                return true;
-            }
-
-        }
-        return false;
-    }
-
-    @Override
-    public int compareTo(TemplateMethod other) {
-        if (this == other) {
-            return 0;
-        } else if (!(other instanceof SpecializationData)) {
-            return super.compareTo(other);
-        }
-        SpecializationData m2 = (SpecializationData) other;
-        int kindOrder = kind.compareTo(m2.kind);
-        if (kindOrder != 0) {
-            return kindOrder;
-        }
-
-        int compare = 0;
-        int order1 = index;
-        int order2 = m2.index;
-        if (order1 != NO_NATURAL_ORDER && order2 != NO_NATURAL_ORDER) {
-            compare = Integer.compare(order1, order2);
-            if (compare != 0) {
-                return compare;
-            }
-        }
-
-        return super.compareTo(other);
-    }
-
-    public void setIndex(int order) {
-        this.index = order;
-    }
-
-    public int getIndex() {
-        return index;
-    }
-
-    public int compareByConcreteness(SpecializationData m2) {
-        int kindOrder = kind.compareTo(m2.kind);
-        if (kindOrder != 0) {
-            return kindOrder;
-        }
-
-        if (getTemplate() != m2.getTemplate()) {
-            throw new UnsupportedOperationException("Cannot compare two specializations with different templates.");
-        }
-        boolean intersects = intersects(m2);
-        int result = 0;
-        if (intersects) {
-            if (this.contains(m2)) {
-                return 1;
-            } else if (m2.contains(this)) {
-                return -1;
-            }
-        }
-
-        result = compareBySignature(m2);
-        if (result != 0) {
-            return result;
-        }
-
-        result = compareGuards(getGuards(), m2.getGuards());
-        if (result != 0) {
-            return result;
-        }
-
-        result = compareAssumptions(getAssumptions(), m2.getAssumptions());
-        if (result != 0) {
-            return result;
-        }
-
-        result = compareParameter(node.getTypeSystem(), getReturnType().getType(), m2.getReturnType().getType());
-        if (result != 0) {
-            return result;
-        }
-
-        result = m2.getExceptions().size() - getExceptions().size();
-        if (result != 0) {
-            return result;
-        }
-
-        return result;
-    }
-
-    public boolean contains(SpecializationData other) {
-        return getContains().contains(other);
-    }
-
-    private int compareAssumptions(List<String> assumptions1, List<String> assumptions2) {
-        Iterator<String> iterator1 = assumptions1.iterator();
-        Iterator<String> iterator2 = assumptions2.iterator();
-        while (iterator1.hasNext() && iterator2.hasNext()) {
-            String a1 = iterator1.next();
-            String a2 = iterator2.next();
-
-            int index1 = getNode().getAssumptions().indexOf(a1);
-            int index2 = getNode().getAssumptions().indexOf(a2);
-            int result = index1 - index2;
-            if (result != 0) {
-                return result;
-            }
-        }
-        if (iterator1.hasNext()) {
-            return -1;
-        } else if (iterator2.hasNext()) {
-            return 1;
-        }
-        return 0;
-    }
-
-    public boolean isContainedBy(SpecializationData next) {
-        if (compareTo(next) > 0) {
-            // must be declared after the current specialization
-            return false;
-        }
-
-        Iterator<ActualParameter> currentSignature = getSignatureParameters().iterator();
-        Iterator<ActualParameter> nextSignature = next.getSignatureParameters().iterator();
-
-        while (currentSignature.hasNext() && nextSignature.hasNext()) {
-            TypeData currentType = currentSignature.next().getTypeSystemType();
-            TypeData prevType = nextSignature.next().getTypeSystemType();
-
-            if (!currentType.isImplicitSubtypeOf(prevType)) {
-                return false;
-            }
-        }
-
-        for (String nextAssumption : next.getAssumptions()) {
-            if (!getAssumptions().contains(nextAssumption)) {
-                return false;
-            }
-        }
-
-        Iterator<GuardExpression> nextGuards = next.getGuards().iterator();
-        while (nextGuards.hasNext()) {
-            GuardExpression nextGuard = nextGuards.next();
-            boolean implied = false;
-            for (GuardExpression currentGuard : getGuards()) {
-                if (currentGuard.implies(nextGuard)) {
-                    implied = true;
-                    break;
-                }
-            }
-            if (!implied) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    public boolean intersects(SpecializationData other) {
-        return intersectsTypeGuards(other) || intersectsMethodGuards(other);
-    }
-
-    private boolean intersectsTypeGuards(SpecializationData other) {
-        final TypeSystemData typeSystem = getTemplate().getTypeSystem();
-        if (typeSystem != other.getTemplate().getTypeSystem()) {
-            throw new IllegalStateException("Cannot compare two methods with different type systems.");
-        }
-
-        Iterator<ActualParameter> signature1 = getSignatureParameters().iterator();
-        Iterator<ActualParameter> signature2 = other.getSignatureParameters().iterator();
-        while (signature1.hasNext() && signature2.hasNext()) {
-            TypeData parameter1 = signature1.next().getTypeSystemType();
-            TypeData parameter2 = signature2.next().getTypeSystemType();
-            if (parameter1 == null || parameter2 == null) {
-                continue;
-            }
-            if (!parameter1.intersects(parameter2)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private boolean intersectsMethodGuards(SpecializationData other) {
-        for (GuardExpression guard1 : getGuards()) {
-            for (GuardExpression guard2 : other.getGuards()) {
-                if (guard1.impliesNot(guard2) || guard2.impliesNot(guard1)) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    private static int compareGuards(List<GuardExpression> guards1, List<GuardExpression> guards2) {
-        Iterator<GuardExpression> signature1 = guards1.iterator();
-        Iterator<GuardExpression> signature2 = guards2.iterator();
-        boolean allSame = true;
-        while (signature1.hasNext() && signature2.hasNext()) {
-            GuardExpression guard1 = signature1.next();
-            GuardExpression guard2 = signature2.next();
-            boolean g1impliesg2 = guard1.implies(guard2);
-            boolean g2impliesg1 = guard2.implies(guard1);
-            if (g1impliesg2 && g2impliesg1) {
-                continue;
-            } else if (g1impliesg2) {
-                return -1;
-            } else if (g2impliesg1) {
-                return 1;
-            } else {
-                allSame = false;
-            }
-        }
-
-        if (allSame) {
-            if (signature1.hasNext()) {
-                return -1;
-            } else if (signature2.hasNext()) {
-                return 1;
-            }
-        }
-
-        return 0;
-    }
-
-    public String createReferenceName() {
-        StringBuilder b = new StringBuilder();
-
-        b.append(getMethodName());
-        b.append("(");
-
-        String sep = "";
-        for (ActualParameter parameter : getParameters()) {
-            b.append(sep);
-            b.append(Utils.getSimpleName(parameter.getType()));
-            sep = ", ";
-        }
-
-        b.append(")");
-        return b.toString();
-    }
-
-    public NodeData getNode() {
-        return node;
-    }
-
-    public void setGuards(List<GuardExpression> guards) {
-        this.guards = guards;
-    }
-
-    public boolean isSpecialized() {
-        return kind == SpecializationKind.SPECIALIZED;
-    }
-
-    public boolean isGeneric() {
-        return kind == SpecializationKind.GENERIC;
-    }
-
-    public boolean isUninitialized() {
-        return kind == SpecializationKind.UNINITIALIZED;
-    }
-
-    public List<SpecializationThrowsData> getExceptions() {
-        return exceptions;
-    }
-
-    public List<GuardExpression> getGuards() {
-        return guards;
-    }
-
-    public void setShortCircuits(List<ShortCircuitData> shortCircuits) {
-        this.shortCircuits = shortCircuits;
-    }
-
-    public List<ShortCircuitData> getShortCircuits() {
-        return shortCircuits;
-    }
-
-    public List<String> getAssumptions() {
-        return assumptions;
-    }
-
-    void setAssumptions(List<String> assumptions) {
-        this.assumptions = assumptions;
-    }
-
-    public SpecializationData findNextSpecialization() {
-        List<SpecializationData> specializations = node.getSpecializations();
-        for (int i = 0; i < specializations.size() - 1; i++) {
-            if (specializations.get(i) == this) {
-                return specializations.get(i + 1);
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature());
-    }
-
-    public boolean equalsGuards(SpecializationData specialization) {
-        if (assumptions.equals(specialization.getAssumptions()) && guards.equals(specialization.getGuards()) && getTypeSignature().equalsParameters(specialization.getTypeSignature())) {
-            return true;
-        }
-        return false;
-    }
-
-    public boolean hasFrame(ProcessorContext context) {
-        for (ActualParameter param : getParameters()) {
-            if (Utils.typeEquals(param.getType(), context.getTruffleTypes().getFrame())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public boolean isReachableAfter(SpecializationData prev) {
-        if (!prev.isSpecialized()) {
-            return true;
-        }
-
-        if (!prev.getExceptions().isEmpty()) {
-            return true;
-        }
-
-        Iterator<ActualParameter> currentSignature = getSignatureParameters().iterator();
-        Iterator<ActualParameter> prevSignature = prev.getSignatureParameters().iterator();
-
-        while (currentSignature.hasNext() && prevSignature.hasNext()) {
-            TypeData currentType = currentSignature.next().getTypeSystemType();
-            TypeData prevType = prevSignature.next().getTypeSystemType();
-
-            if (!currentType.isImplicitSubtypeOf(prevType)) {
-                return true;
-            }
-        }
-
-        for (String prevAssumption : prev.getAssumptions()) {
-            if (!getAssumptions().contains(prevAssumption)) {
-                return true;
-            }
-        }
-
-        Iterator<GuardExpression> prevGuards = prev.getGuards().iterator();
-        Iterator<GuardExpression> currentGuards = getGuards().iterator();
-        while (prevGuards.hasNext()) {
-            GuardExpression prevGuard = prevGuards.next();
-            GuardExpression currentGuard = currentGuards.hasNext() ? currentGuards.next() : null;
-            if (currentGuard == null || !currentGuard.implies(prevGuard)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,448 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.util.*;
-
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.template.TemplateMethod.TypeSignature;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-/**
- * Class creates groups of specializations to optimize the layout of generated executeAndSpecialize
- * and generic execute methods.
- */
-public final class SpecializationGroup {
-
-    private final List<String> assumptions;
-    private final List<TypeGuard> typeGuards;
-    private final List<GuardExpression> guards;
-
-    private final NodeData node;
-    private final SpecializationData specialization;
-    private final List<SpecializationGroup> children = new ArrayList<>();
-
-    private SpecializationGroup parent;
-
-    private SpecializationGroup(SpecializationData data) {
-        this.node = data.getNode();
-        this.assumptions = new ArrayList<>();
-        this.typeGuards = new ArrayList<>();
-        this.guards = new ArrayList<>();
-        this.specialization = data;
-
-        this.assumptions.addAll(data.getAssumptions());
-        TypeSignature sig = data.getTypeSignature();
-        for (int i = 1; i < sig.size(); i++) {
-            typeGuards.add(new TypeGuard(sig.get(i), i - 1));
-        }
-        this.guards.addAll(data.getGuards());
-    }
-
-    public SpecializationGroup(List<SpecializationGroup> children, List<String> assumptionMatches, List<TypeGuard> typeGuardsMatches, List<GuardExpression> guardMatches) {
-        assert !children.isEmpty() : "children must not be empty";
-        this.assumptions = assumptionMatches;
-        this.typeGuards = typeGuardsMatches;
-        this.guards = guardMatches;
-        this.node = children.get(0).node;
-        this.specialization = null;
-        updateChildren(children);
-    }
-
-    public List<TypeGuard> getAllGuards() {
-        List<TypeGuard> collectedGuards = new ArrayList<>();
-        collectedGuards.addAll(typeGuards);
-        if (parent != null) {
-            collectedGuards.addAll(parent.getAllGuards());
-        }
-        return collectedGuards;
-    }
-
-    public TypeGuard findTypeGuard(int signatureIndex) {
-        for (TypeGuard guard : typeGuards) {
-            if (guard.getSignatureIndex() == signatureIndex) {
-                return guard;
-            }
-        }
-        return null;
-    }
-
-    public List<GuardExpression> findElseConnectableGuards() {
-        if (!getTypeGuards().isEmpty() || !getAssumptions().isEmpty()) {
-            return Collections.emptyList();
-        }
-
-        if (getGuards().isEmpty()) {
-            return Collections.emptyList();
-        }
-
-        List<GuardExpression> elseConnectableGuards = new ArrayList<>();
-        int guardIndex = 0;
-        while (guardIndex < getGuards().size() && findNegatedGuardInPrevious(getGuards().get(guardIndex)) != null) {
-            elseConnectableGuards.add(getGuards().get(guardIndex));
-            guardIndex++;
-        }
-
-        return elseConnectableGuards;
-    }
-
-    private GuardExpression findNegatedGuardInPrevious(GuardExpression guard) {
-        SpecializationGroup previous = this.getPreviousGroup();
-        if (previous == null) {
-            return null;
-        }
-        List<GuardExpression> elseConnectedGuards = previous.findElseConnectableGuards();
-
-        if (previous == null || previous.getGuards().size() != elseConnectedGuards.size() + 1) {
-            return null;
-        }
-
-        /* Guard is else branch can be connected in previous specialization. */
-        if (elseConnectedGuards.contains(guard)) {
-            return guard;
-        }
-
-        GuardExpression previousGuard = previous.getGuards().get(elseConnectedGuards.size());
-        if (guard.getResolvedGuard().getMethod().equals(previousGuard.getResolvedGuard().getMethod()) && guard.isNegated() != previousGuard.isNegated()) {
-            return guard;
-        }
-        return null;
-    }
-
-    private void updateChildren(List<SpecializationGroup> childs) {
-        if (!children.isEmpty()) {
-            children.clear();
-        }
-        this.children.addAll(childs);
-        for (SpecializationGroup child : childs) {
-            child.parent = this;
-        }
-    }
-
-    public SpecializationGroup getParent() {
-        return parent;
-    }
-
-    public List<String> getAssumptions() {
-        return assumptions;
-    }
-
-    public List<TypeGuard> getTypeGuards() {
-        return typeGuards;
-    }
-
-    public List<GuardExpression> getGuards() {
-        return guards;
-    }
-
-    public List<SpecializationGroup> getChildren() {
-        return children;
-    }
-
-    public SpecializationData getSpecialization() {
-        return specialization;
-    }
-
-    private static SpecializationGroup combine(List<SpecializationGroup> groups) {
-        if (groups.isEmpty()) {
-            throw new IllegalArgumentException("empty combinations");
-        }
-        if (groups.size() == 1) {
-            return null;
-        }
-
-        List<String> assumptionMatches = new ArrayList<>();
-        List<TypeGuard> typeGuardsMatches = new ArrayList<>();
-        List<GuardExpression> guardMatches = new ArrayList<>();
-
-        SpecializationGroup first = groups.get(0);
-        List<SpecializationGroup> others = groups.subList(1, groups.size());
-
-        outer: for (String assumption : first.assumptions) {
-            for (SpecializationGroup other : others) {
-                if (!other.assumptions.contains(assumption)) {
-                    // assumptions can be combined unordered
-                    continue outer;
-                }
-            }
-            assumptionMatches.add(assumption);
-        }
-
-        outer: for (TypeGuard typeGuard : first.typeGuards) {
-            for (SpecializationGroup other : others) {
-                if (!other.typeGuards.contains(typeGuard)) {
-                    // type guards can be combined unordered
-                    continue outer;
-                }
-            }
-            typeGuardsMatches.add(typeGuard);
-        }
-
-        outer: for (GuardExpression guard : first.guards) {
-            for (SpecializationGroup other : others) {
-                if (!other.guards.contains(guard)) {
-                    // we must break here. One guard may depend on the other.
-                    break outer;
-                }
-            }
-            guardMatches.add(guard);
-        }
-
-        // check for guards for required type casts
-        for (Iterator<GuardExpression> iterator = guardMatches.iterator(); iterator.hasNext();) {
-            GuardExpression guardMatch = iterator.next();
-
-            int signatureIndex = 0;
-            for (ActualParameter parameter : guardMatch.getResolvedGuard().getParameters()) {
-                signatureIndex++;
-                if (!parameter.getSpecification().isSignature()) {
-                    continue;
-                }
-
-                TypeMirror guardType = parameter.getType();
-
-                // object guards can be safely moved up
-                if (Utils.isObject(guardType)) {
-                    continue;
-                }
-
-                // generic guards can be safely moved up
-                SpecializationData generic = first.node.getGenericSpecialization();
-                if (generic != null) {
-                    ActualParameter genericParameter = generic.findParameter(parameter.getLocalName());
-                    if (genericParameter != null && Utils.typeEquals(genericParameter.getType(), guardType)) {
-                        continue;
-                    }
-                }
-
-                // signature index required for moving up guards
-                if (containsIndex(typeGuardsMatches, signatureIndex) || (first.getParent() != null && first.getParent().containsTypeGuardIndex(signatureIndex))) {
-                    continue;
-                }
-
-                iterator.remove();
-                break;
-            }
-        }
-
-        if (assumptionMatches.isEmpty() && typeGuardsMatches.isEmpty() && guardMatches.isEmpty()) {
-            return null;
-        }
-
-        for (SpecializationGroup group : groups) {
-            group.assumptions.removeAll(assumptionMatches);
-            group.typeGuards.removeAll(typeGuardsMatches);
-            group.guards.removeAll(guardMatches);
-        }
-
-        List<SpecializationGroup> newChildren = new ArrayList<>(groups);
-        return new SpecializationGroup(newChildren, assumptionMatches, typeGuardsMatches, guardMatches);
-    }
-
-    private boolean containsTypeGuardIndex(int index) {
-        if (containsIndex(typeGuards, index)) {
-            return true;
-        }
-        if (parent != null) {
-            return parent.containsTypeGuardIndex(index);
-        }
-        return false;
-    }
-
-    private static boolean containsIndex(List<TypeGuard> typeGuards, int signatureIndex) {
-        for (TypeGuard guard : typeGuards) {
-            if (guard.signatureIndex == signatureIndex) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public static SpecializationGroup create(SpecializationData specialization) {
-        return new SpecializationGroup(specialization);
-    }
-
-    public static SpecializationGroup create(List<SpecializationData> specializations) {
-        List<SpecializationGroup> groups = new ArrayList<>();
-        for (SpecializationData specialization : specializations) {
-            groups.add(new SpecializationGroup(specialization));
-        }
-        return new SpecializationGroup(createCombinationalGroups(groups), Collections.<String> emptyList(), Collections.<TypeGuard> emptyList(), Collections.<GuardExpression> emptyList());
-    }
-
-    @Override
-    public String toString() {
-        return "SpecializationGroup [assumptions=" + assumptions + ", typeGuards=" + typeGuards + ", guards=" + guards + "]";
-    }
-
-    private static List<SpecializationGroup> createCombinationalGroups(List<SpecializationGroup> groups) {
-        if (groups.size() <= 1) {
-            return groups;
-        }
-        List<SpecializationGroup> newGroups = new ArrayList<>();
-
-        int i = 0;
-        for (i = 0; i < groups.size();) {
-            SpecializationGroup combined = null;
-            for (int j = groups.size(); j > i + 1; j--) {
-                combined = combine(groups.subList(i, j));
-                if (combined != null) {
-                    break;
-                }
-            }
-            SpecializationGroup newGroup;
-            if (combined == null) {
-                newGroup = groups.get(i);
-                i++;
-            } else {
-                newGroup = combined;
-                List<SpecializationGroup> originalGroups = new ArrayList<>(combined.children);
-                combined.updateChildren(createCombinationalGroups(originalGroups));
-                i += originalGroups.size();
-            }
-
-            newGroups.add(newGroup);
-
-        }
-
-        return newGroups;
-    }
-
-    public SpecializationGroup getPreviousGroup() {
-        if (parent == null || parent.children.isEmpty()) {
-            return null;
-        }
-        int index = parent.children.indexOf(this);
-        if (index <= 0) {
-            return null;
-        }
-        return parent.children.get(index - 1);
-    }
-
-    public int getUncheckedSpecializationIndex() {
-        int groupMaxIndex = getMaxSpecializationIndex();
-
-        int genericIndex = node.getSpecializations().indexOf(node.getGenericSpecialization());
-        if (groupMaxIndex >= genericIndex) {
-            // no minimum state check for an generic index
-            groupMaxIndex = -1;
-        }
-
-        if (groupMaxIndex > -1) {
-            // no minimum state check if already checked by parent group
-            int parentMaxIndex = -1;
-            if (getParent() != null) {
-                parentMaxIndex = getParent().getMaxSpecializationIndex();
-            }
-            if (groupMaxIndex == parentMaxIndex) {
-                groupMaxIndex = -1;
-            }
-        }
-        return groupMaxIndex;
-    }
-
-    public int getMaxSpecializationIndex() {
-        if (specialization != null) {
-            return specialization.getNode().getSpecializations().indexOf(specialization);
-        } else {
-            int max = Integer.MIN_VALUE;
-            for (SpecializationGroup childGroup : getChildren()) {
-                max = Math.max(max, childGroup.getMaxSpecializationIndex());
-            }
-            return max;
-        }
-    }
-
-    public static final class TypeGuard {
-
-        private final int signatureIndex;
-        private final TypeData type;
-
-        public TypeGuard(TypeData type, int signatureIndex) {
-            this.type = type;
-            this.signatureIndex = signatureIndex;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + signatureIndex;
-            result = prime * result + type.hashCode();
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            } else if (obj == null) {
-                return false;
-            } else if (getClass() != obj.getClass()) {
-                return false;
-            }
-
-            TypeGuard other = (TypeGuard) obj;
-            if (signatureIndex != other.signatureIndex) {
-                return false;
-            } else if (!type.equals(other.type)) {
-                return false;
-            }
-            return true;
-        }
-
-        public int getSignatureIndex() {
-            return signatureIndex;
-        }
-
-        public TypeData getType() {
-            return type;
-        }
-    }
-
-    public boolean isTypeGuardUsedInAnyGuardBelow(ProcessorContext context, SpecializationData source, TypeGuard typeGuard) {
-
-        for (GuardExpression guard : guards) {
-            ActualParameter guardParameter = guard.getResolvedGuard().getSignatureParameter(typeGuard.getSignatureIndex());
-            if (guardParameter == null) {
-                // guardParameters are optional
-                continue;
-            }
-            ActualParameter sourceParameter = source.getSignatureParameter(typeGuard.getSignatureIndex());
-            if (sourceParameter.getTypeSystemType().needsCastTo(guardParameter.getType())) {
-                return true;
-            }
-        }
-
-        for (SpecializationGroup group : getChildren()) {
-            if (group.isTypeGuardUsedInAnyGuardBelow(context, source, typeGuard)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGuardData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class SpecializationGuardData extends MessageContainer {
-
-    private final SpecializationData specialization;
-    private final AnnotationValue value;
-    private final String guardMethod;
-    private final boolean onSpecialization;
-    private final boolean onExecution;
-
-    private GuardData guardDeclaration;
-
-    public SpecializationGuardData(SpecializationData specialization, AnnotationValue value, String guardMethod, boolean onSpecialization, boolean onExecution) {
-        this.specialization = specialization;
-        this.guardMethod = guardMethod;
-        this.onSpecialization = onSpecialization;
-        this.onExecution = onExecution;
-        this.value = value;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return specialization.getMessageElement();
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return specialization.getMessageAnnotation();
-    }
-
-    @Override
-    public AnnotationValue getMessageAnnotationValue() {
-        return value;
-    }
-
-    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;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.node;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.SpecializationData.SpecializationKind;
-import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class SpecializationMethodParser extends NodeMethodParser<SpecializationData> {
-
-    public SpecializationMethodParser(ProcessorContext context, NodeData operation) {
-        super(context, operation);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        return createDefaultMethodSpec(method, mirror, true, null);
-    }
-
-    @Override
-    public SpecializationData create(TemplateMethod method, boolean invalid) {
-        return parseSpecialization(method);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return Specialization.class;
-    }
-
-    private SpecializationData parseSpecialization(TemplateMethod method) {
-        AnnotationValue rewriteValue = Utils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn");
-        List<TypeMirror> exceptionTypes = Utils.getAnnotationValueList(TypeMirror.class, method.getMarkerAnnotation(), "rewriteOn");
-        List<SpecializationThrowsData> exceptionData = new ArrayList<>();
-        for (TypeMirror exceptionType : exceptionTypes) {
-            SpecializationThrowsData throwsData = new SpecializationThrowsData(method.getMarkerAnnotation(), rewriteValue, exceptionType);
-            if (!Utils.canThrowType(method.getMethod().getThrownTypes(), exceptionType)) {
-                throwsData.addError("Method must specify a throws clause with the exception type '%s'.", Utils.getQualifiedName(exceptionType));
-            }
-            exceptionData.add(throwsData);
-        }
-
-        Collections.sort(exceptionData, new Comparator<SpecializationThrowsData>() {
-
-            @Override
-            public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) {
-                return Utils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass());
-            }
-        });
-        SpecializationData specialization = new SpecializationData(getNode(), method, SpecializationKind.SPECIALIZED, exceptionData);
-
-        String insertBeforeName = Utils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "insertBefore");
-        if (!insertBeforeName.equals("")) {
-            specialization.setInsertBeforeName(insertBeforeName);
-        }
-
-        List<String> guardDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards");
-        List<GuardExpression> guardExpressions = new ArrayList<>();
-        for (String guardDef : guardDefs) {
-            guardExpressions.add(new GuardExpression(guardDef));
-        }
-        specialization.setGuards(guardExpressions);
-
-        List<String> containsDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "contains");
-        Set<String> containsNames = specialization.getContainsNames();
-        containsNames.clear();
-        if (containsDefs != null) {
-            for (String include : containsDefs) {
-                if (!containsNames.contains(include)) {
-                    specialization.getContainsNames().add(include);
-                } else {
-                    AnnotationValue value = Utils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
-                    specialization.addError(value, "Duplicate contains declaration '%s'.", include);
-                }
-            }
-
-        }
-
-        List<String> assumptionDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "assumptions");
-        specialization.setAssumptions(assumptionDefs);
-
-        for (String assumption : assumptionDefs) {
-            if (!getNode().getAssumptions().contains(assumption)) {
-                specialization.addError("Undeclared assumption '%s' used. Use @NodeAssumptions to declare them.", assumption);
-            }
-        }
-
-        return specialization;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationThrowsData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /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.dsl.processor.node;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class SpecializationThrowsData extends MessageContainer {
-
-    private final AnnotationValue annotationValue;
-    private final AnnotationMirror annotationMirror;
-    private final TypeMirror javaClass;
-    private SpecializationData specialization;
-
-    public SpecializationThrowsData(AnnotationMirror annotationMirror, AnnotationValue value, TypeMirror javaClass) {
-        this.annotationMirror = annotationMirror;
-        this.annotationValue = value;
-        this.javaClass = javaClass;
-    }
-
-    void setSpecialization(SpecializationData specialization) {
-        this.specialization = specialization;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return specialization.getMessageElement();
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return annotationMirror;
-    }
-
-    @Override
-    public AnnotationValue getMessageAnnotationValue() {
-        return annotationValue;
-    }
-
-    public TypeMirror getJavaClass() {
-        return javaClass;
-    }
-
-    public SpecializationData getSpecialization() {
-        return specialization;
-    }
-
-    public AnnotationMirror getAnnotationMirror() {
-        return annotationMirror;
-    }
-
-    public SpecializationData getTransitionTo() {
-        return specialization.findNextSpecialization();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/AbstractParser.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.MessageContainer.Message;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+public abstract class AbstractParser<M extends Template> {
+
+    protected final ProcessorContext context;
+    protected final ProcessingEnvironment processingEnv;
+
+    protected final Log log;
+
+    public AbstractParser() {
+        this.context = ProcessorContext.getInstance();
+        this.processingEnv = context.getEnvironment();
+        this.log = context.getLog();
+    }
+
+    public final M parse(Element element) {
+        M model = null;
+        try {
+            AnnotationMirror mirror = null;
+            if (getAnnotationType() != null) {
+                mirror = ElementUtils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType());
+            }
+
+            if (!context.getTruffleTypes().verify(context, element, mirror)) {
+                return null;
+            }
+            model = parse(element, mirror);
+            if (model == null) {
+                return null;
+            }
+
+            redirectMessages(new HashSet<MessageContainer>(), model, model);
+            model.emitMessages(context, log);
+            return filterErrorElements(model);
+        } catch (CompileErrorException e) {
+            log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage());
+            return null;
+        }
+    }
+
+    private void redirectMessages(Set<MessageContainer> visitedSinks, MessageContainer model, MessageContainer baseContainer) {
+        List<Message> messages = model.getMessages();
+        for (int i = messages.size() - 1; i >= 0; i--) {
+            Message message = messages.get(i);
+            if (!ElementUtils.isEnclosedIn(baseContainer.getMessageElement(), message.getOriginalContainer().getMessageElement())) {
+                // redirect message
+                MessageContainer original = message.getOriginalContainer();
+                String text = wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText());
+                Message redirectedMessage = new Message(null, baseContainer, text, message.getKind());
+                model.getMessages().remove(i);
+                baseContainer.getMessages().add(redirectedMessage);
+            }
+        }
+
+        for (MessageContainer childContainer : model) {
+            if (visitedSinks.contains(childContainer)) {
+                continue;
+            }
+            visitedSinks.add(childContainer);
+
+            MessageContainer newBase = baseContainer;
+            if (childContainer.getBaseContainer() != null) {
+                newBase = childContainer.getBaseContainer();
+            }
+            redirectMessages(visitedSinks, childContainer, newBase);
+        }
+    }
+
+    private static String wrapText(Element element, AnnotationMirror mirror, String text) {
+        StringBuilder b = new StringBuilder();
+        if (element != null) {
+            b.append("Element " + element.toString());
+        }
+        if (mirror != null) {
+            b.append(" at annotation @" + ElementUtils.getSimpleName(mirror.getAnnotationType()));
+        }
+
+        if (b.length() > 0) {
+            b.append(" is erroneous: ").append(text);
+            return b.toString();
+        } else {
+            return text;
+        }
+    }
+
+    protected M filterErrorElements(M model) {
+        return model.hasErrors() ? null : model;
+    }
+
+    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();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class CreateCastParser extends NodeMethodParser<CreateCastData> {
+
+    public CreateCastParser(ProcessorContext context, NodeData operation) {
+        super(context, operation);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return CreateCast.class;
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        List<String> childNames = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
+        NodeChildData foundChild = null;
+        for (String childName : childNames) {
+            foundChild = getNode().findChild(childName);
+            if (foundChild != null) {
+                break;
+            }
+        }
+        TypeMirror baseType = getContext().getTruffleTypes().getNode();
+        if (foundChild != null) {
+            baseType = foundChild.getOriginalType();
+        }
+
+        MethodSpec spec = new MethodSpec(new InheritsParameterSpec("child", baseType));
+        addDefaultFieldMethodSpec(spec);
+        ParameterSpec childSpec = new ParameterSpec("castedChild", baseType);
+        childSpec.setSignature(true);
+        spec.addRequired(childSpec);
+        return spec;
+    }
+
+    @Override
+    public CreateCastData create(TemplateMethod method, boolean invalid) {
+        AnnotationMirror mirror = method.getMarkerAnnotation();
+        List<String> childNames = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
+        CreateCastData cast = new CreateCastData(method, childNames);
+        AnnotationValue value = ElementUtils.getAnnotationValue(mirror, "value");
+        TypeMirror type = null;
+        if (childNames == null || childNames.isEmpty()) {
+            cast.addError(value, "No value specified but required.");
+            return cast;
+        }
+
+        for (String childName : childNames) {
+            NodeChildData child = getNode().findChild(childName);
+            if (child == null) {
+                // error
+                cast.addError(value, "Specified child '%s' not found.", childName);
+                continue;
+            }
+            if (type == null) {
+                type = child.getNodeType();
+            } else if (!ElementUtils.typeEquals(type, child.getNodeType())) {
+                cast.addError(value, "All child nodes for a cast must have the same node type.");
+                continue;
+            }
+        }
+        return cast;
+    }
+
+    private static class InheritsParameterSpec extends ParameterSpec {
+
+        public InheritsParameterSpec(String name, TypeMirror... allowedTypes) {
+            super(name, Arrays.asList(allowedTypes));
+        }
+
+        @Override
+        public boolean matches(TypeMirror actualType) {
+            boolean found = false;
+            for (TypeMirror specType : getAllowedTypes()) {
+                if (ElementUtils.isAssignable(actualType, specType)) {
+                    found = true;
+                    break;
+                }
+            }
+            return found;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class ExecutableTypeMethodParser extends NodeMethodParser<ExecutableTypeData> {
+
+    public ExecutableTypeMethodParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+        setEmitErrors(false);
+        setParseNullOnError(false);
+        setUseVarArgs(true);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null);
+        List<ParameterSpec> requiredSpecs = new ArrayList<>(spec.getRequired());
+        spec.getRequired().clear();
+
+        List<TypeMirror> allowedTypes = getNode().getTypeSystem().getPrimitiveTypeMirrors();
+        for (ParameterSpec originalSpec : requiredSpecs) {
+            spec.addRequired(new ParameterSpec(originalSpec, allowedTypes));
+        }
+        spec.setIgnoreAdditionalSpecifications(true);
+        spec.setIgnoreAdditionalParameters(true);
+        spec.setVariableRequiredParameters(true);
+        // varargs
+        ParameterSpec otherParameters = new ParameterSpec("other", allowedTypes);
+        otherParameters.setSignature(true);
+        spec.addRequired(otherParameters);
+        return spec;
+    }
+
+    @Override
+    public final boolean isParsable(ExecutableElement method) {
+        if (method.getModifiers().contains(Modifier.STATIC)) {
+            return false;
+        } else if (method.getModifiers().contains(Modifier.NATIVE)) {
+            return false;
+        }
+        return method.getSimpleName().toString().startsWith("execute");
+    }
+
+    @Override
+    protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
+        List<TypeMirror> types = new ArrayList<>(getNode().getTypeSystem().getPrimitiveTypeMirrors());
+        types.add(getNode().getTypeSystem().getVoidType().getPrimitiveType());
+        return types;
+    }
+
+    @Override
+    public ExecutableTypeData create(TemplateMethod method, boolean invalid) {
+        TypeData resolvedType = method.getReturnType().getTypeSystemType();
+        return new ExecutableTypeData(method, method.getMethod(), 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.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GenericParser.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind;
+
+public class GenericParser extends NodeMethodParser<SpecializationData> {
+
+    public GenericParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        return createDefaultMethodSpec(method, mirror, true, null);
+    }
+
+    @Override
+    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
+        List<ExecutableTypeData> execTypes = execution.getChild().findGenericExecutableTypes(getContext());
+        List<TypeMirror> types = new ArrayList<>();
+        for (ExecutableTypeData type : execTypes) {
+            types.add(type.getType().getPrimitiveType());
+        }
+        ParameterSpec spec = new ParameterSpec(execution.getName(), types);
+        spec.setExecution(execution);
+        return spec;
+    }
+
+    @Override
+    public SpecializationData create(TemplateMethod method, boolean invalid) {
+        return new SpecializationData(getNode(), method, SpecializationKind.GENERIC);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return Generic.class;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class GuardParser extends NodeMethodParser<GuardData> {
+
+    private final Set<String> guardNames;
+    private final TemplateMethod compatibleSource;
+
+    public GuardParser(ProcessorContext context, NodeData node, TemplateMethod compatibleSource, Set<String> guardNames) {
+        super(context, node);
+        this.guardNames = guardNames;
+        this.compatibleSource = compatibleSource;
+        setEmitErrors(false);
+        setParseNullOnError(false);
+    }
+
+    @Override
+    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
+        return super.createValueParameterSpec(execution);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null);
+        spec.setIgnoreAdditionalSpecifications(true);
+        if (compatibleSource != null) {
+            spec.getRequired().clear();
+            for (Parameter parameter : compatibleSource.getRequiredParameters()) {
+                spec.addRequired(new ParameterSpec(parameter.getSpecification(), ElementUtils.getAssignableTypes(getContext(), parameter.getType())));
+            }
+        }
+        return spec;
+    }
+
+    @Override
+    protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
+        Set<TypeMirror> typeMirrors = new LinkedHashSet<>();
+        typeMirrors.addAll(nodeData.getTypeSystem().getPrimitiveTypeMirrors());
+        typeMirrors.addAll(nodeData.getTypeSystem().getBoxedTypeMirrors());
+        return new ArrayList<>(typeMirrors);
+    }
+
+    @Override
+    protected ParameterSpec createReturnParameterSpec() {
+        return new ParameterSpec("returnType", getContext().getType(boolean.class));
+    }
+
+    @Override
+    public boolean isParsable(ExecutableElement method) {
+        return guardNames.contains(method.getSimpleName().toString());
+    }
+
+    @Override
+    public GuardData create(TemplateMethod method, boolean invalid) {
+        Implies impliesAnnotation = method.getMethod().getAnnotation(Implies.class);
+        String[] impliesExpressions = new String[0];
+        if (impliesAnnotation != null) {
+            impliesExpressions = impliesAnnotation.value();
+        }
+        List<GuardExpression> guardExpressions = new ArrayList<>();
+        for (String string : impliesExpressions) {
+            guardExpressions.add(new GuardExpression(string));
+        }
+        return new GuardData(method, guardExpressions);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ImplicitCastParser.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class ImplicitCastParser extends TypeSystemMethodParser<ImplicitCastData> {
+
+    public ImplicitCastParser(ProcessorContext context, TypeSystemData typeSystem) {
+        super(context, typeSystem);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return ImplicitCast.class;
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        List<TypeMirror> types = new ArrayList<>();
+        for (TypeData typeData : getTypeSystem().getTypes()) {
+            types.add(typeData.getPrimitiveType());
+        }
+        MethodSpec spec = new MethodSpec(new ParameterSpec("target", types));
+        spec.addRequired(new ParameterSpec("source", types));
+        return spec;
+    }
+
+    @Override
+    public ImplicitCastData create(TemplateMethod method, boolean invalid) {
+        if (invalid) {
+            return new ImplicitCastData(method, null, null);
+        }
+
+        Parameter target = method.findParameter("targetValue");
+        Parameter source = method.findParameter("sourceValue");
+
+        TypeData targetType = target.getTypeSystemType();
+        TypeData sourceType = source.getTypeSystemType();
+
+        if (targetType.equals(sourceType)) {
+            method.addError("Target type and source type of an @%s must not be the same type.", ImplicitCast.class.getSimpleName());
+        }
+
+        return new ImplicitCastData(method, sourceType, targetType);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeExecutionData.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
+
+public class NodeExecutionData {
+
+    private final NodeChildData child;
+    private final String name;
+    private final int index;
+    private final boolean shortCircuit;
+
+    public NodeExecutionData(NodeChildData child, int index, boolean shortCircuit) {
+        this.child = child;
+        this.index = index;
+        this.shortCircuit = shortCircuit;
+        this.name = createName();
+    }
+
+    private String createName() {
+        if (isIndexed()) {
+            return child.getName() + index;
+        }
+        return child.getName();
+    }
+
+    public TypeMirror getNodeType() {
+        TypeMirror type;
+        if (child.getCardinality() == Cardinality.MANY && child.getNodeType().getKind() == TypeKind.ARRAY) {
+            type = ((ArrayType) child.getNodeType()).getComponentType();
+        } else {
+            type = child.getNodeType();
+        }
+        return type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public NodeChildData getChild() {
+        return child;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public boolean isIndexed() {
+        return index > -1;
+    }
+
+    public boolean isShortCircuit() {
+        return shortCircuit;
+    }
+
+    public String getShortCircuitId() {
+        return createShortCircuitId(child, index);
+    }
+
+    public static String createShortCircuitId(NodeChildData child, int varArgsIndex) {
+        String shortCircuitName = child.getName();
+        if (child.getCardinality().isMany()) {
+            shortCircuitName = shortCircuitName + "[" + varArgsIndex + "]";
+        }
+        return shortCircuitName;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public abstract class NodeMethodParser<E extends TemplateMethod> extends TemplateMethodParser<NodeData, E> {
+
+    public NodeMethodParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+    }
+
+    public NodeData getNode() {
+        return template;
+    }
+
+    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
+        ParameterSpec spec = new ParameterSpec(execution.getName(), nodeTypeMirrors(execution.getChild().getNodeData()));
+        spec.setExecution(execution);
+        return spec;
+    }
+
+    protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
+        Set<TypeMirror> typeMirrors = new LinkedHashSet<>();
+
+        for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) {
+            typeMirrors.add(typeData.getType().getPrimitiveType());
+        }
+
+        typeMirrors.add(nodeData.getTypeSystem().getGenericType());
+
+        return new ArrayList<>(typeMirrors);
+    }
+
+    protected ParameterSpec createReturnParameterSpec() {
+        ParameterSpec returnValue = new ParameterSpec("returnValue", nodeTypeMirrors(getNode()));
+        returnValue.setExecution(getNode().getThisExecution());
+        return returnValue;
+    }
+
+    @Override
+    public boolean isParsable(ExecutableElement method) {
+        if (getAnnotationType() != null) {
+            return ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
+        }
+
+        return true;
+    }
+
+    @SuppressWarnings("unused")
+    protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, boolean shortCircuitsEnabled, String shortCircuitName) {
+        MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec());
+
+        addDefaultFrame(methodSpec);
+        addDefaultFieldMethodSpec(methodSpec);
+        addDefaultChildren(shortCircuitsEnabled, shortCircuitName, methodSpec);
+
+        return methodSpec;
+    }
+
+    private void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec spec) {
+        if (getNode().getChildren() == null) {
+            // children are null when parsing executable types
+            return;
+        }
+
+        for (NodeExecutionData execution : getNode().getChildExecutions()) {
+            if (breakName != null && execution.getShortCircuitId().equals(breakName)) {
+                break;
+            }
+
+            if (execution.isShortCircuit() && shortCircuitsEnabled) {
+                spec.addRequired(new ParameterSpec(shortCircuitValueName(execution.getName()), getContext().getType(boolean.class)));
+            }
+            spec.addRequired(createValueParameterSpec(execution));
+        }
+    }
+
+    private void addDefaultFrame(MethodSpec methodSpec) {
+        if (getNode().supportsFrame()) {
+            methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame()));
+        }
+    }
+
+    protected void addDefaultFieldMethodSpec(MethodSpec methodSpec) {
+        for (NodeFieldData field : getNode().getFields()) {
+            if (field.getGetter() == null) {
+                ParameterSpec spec = new ParameterSpec(field.getName(), field.getType());
+                spec.setLocal(true);
+                methodSpec.addOptional(spec);
+            }
+        }
+    }
+
+    private static String shortCircuitValueName(String valueName) {
+        return "has" + ElementUtils.firstLetterUpperCase(valueName);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,1353 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.compiler.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
+import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind;
+import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature;
+
+public class NodeParser extends AbstractParser<NodeData> {
+
+    public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class,
+                    NodeChildren.class);
+
+    private Map<String, NodeData> parsedNodes;
+
+    @Override
+    protected NodeData parse(Element element, AnnotationMirror mirror) {
+        NodeData node = null;
+        try {
+            parsedNodes = new HashMap<>();
+            node = resolveNode((TypeElement) element);
+            if (Log.DEBUG) {
+                NodeData parsed = parsedNodes.get(ElementUtils.getQualifiedName((TypeElement) element));
+                if (node != null) {
+                    String dump = parsed.dump();
+                    log.message(Kind.ERROR, null, null, null, dump);
+                }
+            }
+        } finally {
+            parsedNodes = null;
+        }
+
+        return node;
+    }
+
+    @Override
+    protected NodeData filterErrorElements(NodeData model) {
+        for (Iterator<NodeData> iterator = model.getEnclosingNodes().iterator(); iterator.hasNext();) {
+            NodeData node = filterErrorElements(iterator.next());
+            if (node == null) {
+                iterator.remove();
+            }
+        }
+        if (model.hasErrors()) {
+            return null;
+        }
+        return model;
+    }
+
+    @Override
+    public boolean isDelegateToRootDeclaredType() {
+        return true;
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return null;
+    }
+
+    @Override
+    public List<Class<? extends Annotation>> getTypeDelegatedAnnotationTypes() {
+        return ANNOTATIONS;
+    }
+
+    private NodeData resolveNode(TypeElement rootType) {
+        String typeName = ElementUtils.getQualifiedName(rootType);
+        if (parsedNodes.containsKey(typeName)) {
+            return parsedNodes.get(typeName);
+        }
+
+        List<NodeData> enclosedNodes = new ArrayList<>();
+        for (TypeElement enclosedType : ElementFilter.typesIn(rootType.getEnclosedElements())) {
+            NodeData enclosedChild = resolveNode(enclosedType);
+            if (enclosedChild != null) {
+                enclosedNodes.add(enclosedChild);
+            }
+        }
+
+        NodeData node = parseNode(rootType);
+        if (node == null && !enclosedNodes.isEmpty()) {
+            node = new NodeData(context, rootType);
+        }
+
+        if (node != null) {
+            for (NodeData enclosedNode : enclosedNodes) {
+                node.addEnclosedNode(enclosedNode);
+            }
+        }
+
+        parsedNodes.put(typeName, node);
+        return node;
+    }
+
+    private NodeData parseNode(TypeElement originalTemplateType) {
+        // reloading the type elements is needed for ecj
+        TypeElement templateType = ElementUtils.fromTypeMirror(context.reloadTypeElement(originalTemplateType));
+
+        if (ElementUtils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) {
+            // generated nodes should not get called again.
+            return null;
+        }
+
+        List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType);
+        if (!ElementUtils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) {
+            return null;
+        }
+        List<? extends Element> elements = CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType);
+
+        NodeData node = parseNodeData(templateType, elements, lookupTypes);
+        if (node.hasErrors()) {
+            return node; // error sync point
+        }
+
+        initializeChildren(node);
+
+        node.getSpecializations().addAll(new SpecializationMethodParser(context, node).parse(elements));
+        node.getSpecializations().addAll(new GenericParser(context, node).parse(elements));
+        node.getCasts().addAll(new CreateCastParser(context, node).parse(elements));
+        node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(elements));
+
+        if (node.hasErrors()) {
+            return node;  // error sync point
+        }
+
+        verifySpecializationSameLength(node);
+        initializeSpecializations(elements, node);
+        initializeShortCircuits(node); // requires specializations and polymorphic specializations
+
+        verifyVisibilities(node);
+        verifyMissingAbstractMethods(node, elements);
+        verifyConstructors(node);
+        verifyNamingConvention(node.getShortCircuits(), "needs");
+        verifySpecializationThrows(node);
+        return node;
+    }
+
+    private NodeData parseNodeData(TypeElement templateType, List<? extends Element> elements, List<TypeElement> typeHierarchy) {
+        AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class);
+        if (typeSystemMirror == null) {
+            NodeData nodeData = new NodeData(context, templateType);
+            nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), ElementUtils.getQualifiedName(templateType));
+            return nodeData;
+        }
+
+        TypeMirror typeSystemType = ElementUtils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value");
+        final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true);
+        if (typeSystem == null) {
+            NodeData nodeData = new NodeData(context, templateType);
+            nodeData.addError("The used type system '%s' is invalid or not a Node.", ElementUtils.getQualifiedName(typeSystemType));
+            return nodeData;
+        }
+
+        List<String> assumptionsList = new ArrayList<>();
+        for (int i = typeHierarchy.size() - 1; i >= 0; i--) {
+            TypeElement type = typeHierarchy.get(i);
+            AnnotationMirror assumptions = ElementUtils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class);
+            if (assumptions != null) {
+                List<String> assumptionStrings = ElementUtils.getAnnotationValueList(String.class, assumptions, "value");
+                for (String string : assumptionStrings) {
+                    if (assumptionsList.contains(string)) {
+                        assumptionsList.remove(string);
+                    }
+                    assumptionsList.add(string);
+                }
+            }
+        }
+        AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class);
+        String shortName = null;
+        if (nodeInfoMirror != null) {
+            shortName = ElementUtils.getAnnotationValue(String.class, nodeInfoMirror, "shortName");
+        }
+
+        List<NodeFieldData> fields = parseFields(typeHierarchy, elements);
+        List<NodeChildData> children = parseChildren(typeHierarchy, elements);
+        List<NodeExecutionData> executions = parseExecutions(children, elements);
+
+        NodeData nodeData = new NodeData(context, templateType, shortName, typeSystem, children, executions, fields, assumptionsList);
+        nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
+
+        parsedNodes.put(ElementUtils.getQualifiedName(templateType), nodeData);
+
+        return nodeData;
+    }
+
+    private List<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) {
+        Set<String> names = new HashSet<>();
+
+        List<NodeFieldData> fields = new ArrayList<>();
+        for (VariableElement field : ElementFilter.fieldsIn(elements)) {
+            if (field.getModifiers().contains(Modifier.STATIC)) {
+                continue;
+            }
+            if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) {
+                String name = field.getSimpleName().toString();
+                fields.add(new NodeFieldData(field, null, field.asType(), name, false));
+                names.add(name);
+            }
+        }
+
+        List<TypeElement> reversedTypeHierarchy = new ArrayList<>(typeHierarchy);
+        Collections.reverse(reversedTypeHierarchy);
+        for (TypeElement typeElement : reversedTypeHierarchy) {
+            AnnotationMirror nodeChildrenMirror = ElementUtils.findAnnotationMirror(processingEnv, typeElement, NodeFields.class);
+            List<AnnotationMirror> children = ElementUtils.collectAnnotations(context, nodeChildrenMirror, "value", typeElement, NodeField.class);
+
+            for (AnnotationMirror mirror : children) {
+                String name = ElementUtils.firstLetterLowerCase(ElementUtils.getAnnotationValue(String.class, mirror, "name"));
+                TypeMirror type = ElementUtils.getAnnotationValue(TypeMirror.class, mirror, "type");
+
+                NodeFieldData field = new NodeFieldData(typeElement, mirror, type, name, true);
+                if (name.isEmpty()) {
+                    field.addError(ElementUtils.getAnnotationValue(mirror, "name"), "Field name cannot be empty.");
+                } else if (names.contains(name)) {
+                    field.addError(ElementUtils.getAnnotationValue(mirror, "name"), "Duplicate field name '%s'.", name);
+                }
+                names.add(name);
+
+                fields.add(field);
+            }
+        }
+
+        for (NodeFieldData nodeFieldData : fields) {
+            nodeFieldData.setGetter(findGetter(elements, nodeFieldData.getName(), nodeFieldData.getType()));
+        }
+
+        return fields;
+    }
+
+    private List<NodeChildData> parseChildren(final List<TypeElement> typeHierarchy, List<? extends Element> elements) {
+        Set<String> shortCircuits = new HashSet<>();
+        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
+            if (mirror != null) {
+                shortCircuits.add(ElementUtils.getAnnotationValue(String.class, mirror, "value"));
+            }
+        }
+        Map<String, TypeMirror> castNodeTypes = new HashMap<>();
+        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, CreateCast.class);
+            if (mirror != null) {
+                List<String> children = (ElementUtils.getAnnotationValueList(String.class, mirror, "value"));
+                if (children != null) {
+                    for (String child : children) {
+                        castNodeTypes.put(child, method.getReturnType());
+                    }
+                }
+            }
+        }
+
+        List<NodeChildData> parsedChildren = new ArrayList<>();
+        List<TypeElement> typeHierarchyReversed = new ArrayList<>(typeHierarchy);
+        Collections.reverse(typeHierarchyReversed);
+        for (TypeElement type : typeHierarchyReversed) {
+            AnnotationMirror nodeChildrenMirror = ElementUtils.findAnnotationMirror(processingEnv, type, NodeChildren.class);
+
+            TypeMirror nodeClassType = type.getSuperclass();
+            if (!ElementUtils.isAssignable(nodeClassType, context.getTruffleTypes().getNode())) {
+                nodeClassType = null;
+            }
+
+            List<AnnotationMirror> children = ElementUtils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class);
+            int index = 0;
+            for (AnnotationMirror childMirror : children) {
+                String name = ElementUtils.getAnnotationValue(String.class, childMirror, "value");
+                if (name.equals("")) {
+                    name = "child" + index;
+                }
+
+                Cardinality cardinality = Cardinality.ONE;
+
+                TypeMirror childType = inheritType(childMirror, "type", nodeClassType);
+                if (childType.getKind() == TypeKind.ARRAY) {
+                    cardinality = Cardinality.MANY;
+                }
+
+                TypeMirror originalChildType = childType;
+                TypeMirror castNodeType = castNodeTypes.get(name);
+                if (castNodeType != null) {
+                    childType = castNodeType;
+                }
+
+                Element getter = findGetter(elements, name, childType);
+
+                NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality);
+
+                parsedChildren.add(nodeChild);
+
+                if (nodeChild.getNodeType() == null) {
+                    nodeChild.addError("No valid node type could be resoleved.");
+                }
+                if (nodeChild.hasErrors()) {
+                    continue;
+                }
+
+                index++;
+            }
+        }
+
+        List<NodeChildData> filteredChildren = new ArrayList<>();
+        Set<String> encounteredNames = new HashSet<>();
+        for (int i = parsedChildren.size() - 1; i >= 0; i--) {
+            NodeChildData child = parsedChildren.get(i);
+            if (!encounteredNames.contains(child.getName())) {
+                filteredChildren.add(0, child);
+                encounteredNames.add(child.getName());
+            }
+        }
+
+        for (NodeChildData child : filteredChildren) {
+            List<String> executeWithStrings = ElementUtils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith");
+            AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith");
+            List<NodeChildData> executeWith = new ArrayList<>();
+            for (String executeWithString : executeWithStrings) {
+
+                if (child.getName().equals(executeWithString)) {
+                    child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString);
+                    continue;
+                }
+
+                NodeChildData found = null;
+                boolean before = true;
+                for (NodeChildData resolveChild : filteredChildren) {
+                    if (resolveChild == child) {
+                        before = false;
+                        continue;
+                    }
+                    if (resolveChild.getName().equals(executeWithString)) {
+                        found = resolveChild;
+                        break;
+                    }
+                }
+
+                if (found == null) {
+                    child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString);
+                    continue;
+                } else if (!before) {
+                    child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString,
+                                    executeWithString);
+                    continue;
+                }
+                executeWith.add(found);
+            }
+            child.setExecuteWith(executeWith);
+            if (child.getNodeData() == null) {
+                continue;
+            }
+        }
+
+        return filteredChildren;
+    }
+
+    private List<NodeExecutionData> parseExecutions(List<NodeChildData> children, List<? extends Element> elements) {
+        if (children == null) {
+            return null;
+        }
+
+        // pre-parse short circuits
+        Set<String> shortCircuits = new HashSet<>();
+        List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
+        for (ExecutableElement method : methods) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
+            if (mirror != null) {
+                shortCircuits.add(ElementUtils.getAnnotationValue(String.class, mirror, "value"));
+            }
+        }
+
+        boolean hasVarArgs = false;
+        int maxSignatureSize = 0;
+        if (!children.isEmpty()) {
+            int lastIndex = children.size() - 1;
+            hasVarArgs = children.get(lastIndex).getCardinality() == Cardinality.MANY;
+            if (hasVarArgs) {
+                maxSignatureSize = lastIndex;
+            } else {
+                maxSignatureSize = children.size();
+            }
+        }
+
+        // pre-parse specializations
+        for (ExecutableElement method : methods) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class);
+            if (mirror == null) {
+                continue;
+            }
+
+            int currentArgumentCount = 0;
+            boolean skipShortCircuit = false;
+            for (VariableElement var : method.getParameters()) {
+                TypeMirror type = var.asType();
+                if (currentArgumentCount == 0) {
+                    // skip optionals
+                    if (ElementUtils.typeEquals(type, context.getTruffleTypes().getFrame())) {
+                        continue;
+                    }
+                    // TODO skip optional fields?
+                }
+                int childIndex = currentArgumentCount < children.size() ? currentArgumentCount : children.size() - 1;
+                if (childIndex == -1) {
+                    continue;
+                }
+                if (!skipShortCircuit) {
+                    NodeChildData child = children.get(childIndex);
+                    if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentCount - childIndex))) {
+                        skipShortCircuit = true;
+                        continue;
+                    }
+                } else {
+                    skipShortCircuit = false;
+                }
+
+                currentArgumentCount++;
+            }
+            maxSignatureSize = Math.max(maxSignatureSize, currentArgumentCount);
+        }
+
+        List<NodeExecutionData> executions = new ArrayList<>();
+        for (int i = 0; i < maxSignatureSize; i++) {
+            int childIndex = i;
+            boolean varArg = false;
+            if (childIndex >= children.size() - 1) {
+                if (hasVarArgs) {
+                    childIndex = children.size() - 1;
+                    varArg = hasVarArgs;
+                } else if (childIndex >= children.size()) {
+                    break;
+                }
+            }
+            int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1;
+            NodeChildData child = children.get(childIndex);
+            boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, varArgsIndex));
+            executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit));
+        }
+        return executions;
+    }
+
+    private static Map<Integer, List<ExecutableTypeData>> groupExecutableTypes(List<ExecutableTypeData> executableTypes) {
+        Map<Integer, List<ExecutableTypeData>> groupedTypes = new TreeMap<>();
+        for (ExecutableTypeData type : executableTypes) {
+            int evaluatedCount = type.getEvaluatedCount();
+
+            List<ExecutableTypeData> types = groupedTypes.get(evaluatedCount);
+            if (types == null) {
+                types = new ArrayList<>();
+                groupedTypes.put(evaluatedCount, types);
+            }
+            types.add(type);
+        }
+
+        for (List<ExecutableTypeData> types : groupedTypes.values()) {
+            Collections.sort(types);
+        }
+        return groupedTypes;
+    }
+
+    private void initializeChildren(NodeData node) {
+        for (NodeChildData nodeChild : node.getChildren()) {
+            NodeData fieldNodeData = resolveNode(ElementUtils.fromTypeMirror(nodeChild.getNodeType()));
+            nodeChild.setNode(fieldNodeData);
+            if (fieldNodeData == null) {
+                nodeChild.addError("Node type '%s' is invalid or not a valid Node.", ElementUtils.getQualifiedName(nodeChild.getNodeType()));
+            } else if (!ElementUtils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) {
+                nodeChild.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(),
+                                NodeChild.class.getSimpleName(), ElementUtils.getSimpleName(node.getTypeSystem().getTemplateType()),
+                                ElementUtils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType()));
+            }
+            if (fieldNodeData != null) {
+                List<ExecutableTypeData> types = nodeChild.findGenericExecutableTypes(context);
+                if (types.isEmpty()) {
+                    AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(nodeChild.getMessageAnnotation(), "executeWith");
+                    nodeChild.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", nodeChild.getExecuteWith().size(),
+                                    ElementUtils.getSimpleName(nodeChild.getNodeType()));
+                }
+            }
+        }
+    }
+
+    private void initializeSpecializations(List<? extends Element> elements, final NodeData node) {
+        if (node.getSpecializations().isEmpty()) {
+            return;
+        }
+
+        initializeGuards(elements, node);
+        initializeGeneric(node);
+        initializeUninitialized(node);
+        initializeOrder(node);
+        initializePolymorphism(node); // requires specializations
+        initializeReachability(node);
+        initializeContains(node);
+
+        if (!node.hasErrors()) {
+            initializeExceptions(node);
+        }
+        resolveContains(node);
+
+        List<SpecializationData> needsId = new ArrayList<>();
+        for (SpecializationData specialization : node.getSpecializations()) {
+            if (specialization.isGeneric()) {
+                specialization.setId("Generic");
+            } else if (specialization.isUninitialized()) {
+                specialization.setId("Uninitialized");
+            } else if (specialization.isPolymorphic()) {
+                specialization.setId("Polymorphic");
+            } else if (specialization.isSpecialized()) {
+                needsId.add(specialization);
+            } else {
+                throw new AssertionError();
+            }
+        }
+
+        // verify specialization parameter length
+        List<String> ids = initializeSpecializationIds(needsId);
+        for (int i = 0; i < ids.size(); i++) {
+            needsId.get(i).setId(ids.get(i));
+        }
+
+    }
+
+    private static void initializeOrder(NodeData node) {
+        List<SpecializationData> specializations = node.getSpecializations();
+        Collections.sort(specializations);
+
+        for (SpecializationData specialization : specializations) {
+            String searchName = specialization.getInsertBeforeName();
+            if (searchName == null || specialization.getMethod() == null) {
+                continue;
+            }
+            SpecializationData found = lookupSpecialization(node, searchName);
+            if (found == null || found.getMethod() == null) {
+                AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "insertBefore");
+                specialization.addError(value, "The referenced specialization '%s' could not be found.", searchName);
+                continue;
+            }
+
+            ExecutableElement currentMethod = specialization.getMethod();
+            ExecutableElement insertBeforeMethod = found.getMethod();
+
+            TypeMirror currentEnclosedType = currentMethod.getEnclosingElement().asType();
+            TypeMirror insertBeforeEnclosedType = insertBeforeMethod.getEnclosingElement().asType();
+
+            if (ElementUtils.typeEquals(currentEnclosedType, insertBeforeEnclosedType) || !ElementUtils.isSubtype(currentEnclosedType, insertBeforeEnclosedType)) {
+                AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "insertBefore");
+                specialization.addError(value, "Specializations can only be inserted before specializations in superclasses.", searchName);
+                continue;
+            }
+
+            specialization.setInsertBefore(found);
+        }
+
+        int endIndex = specializations.size() - 1;
+        for (int i = endIndex; i >= 0; i--) {
+            SpecializationData specialization = specializations.get(i);
+            if (specialization.isGeneric() || specialization.isPolymorphic()) {
+                endIndex--;
+                continue;
+            }
+
+            SpecializationData insertBefore = specialization.getInsertBefore();
+            if (insertBefore != null) {
+                int insertIndex = specializations.indexOf(insertBefore);
+                if (insertIndex < i) {
+                    List<SpecializationData> range = new ArrayList<>(specializations.subList(i, endIndex + 1));
+                    specializations.removeAll(range);
+                    specializations.addAll(insertIndex, range);
+                }
+            }
+        }
+
+        for (int i = 0; i < specializations.size(); i++) {
+            specializations.get(i).setIndex(i);
+        }
+    }
+
+    private static void initializeExceptions(NodeData node) {
+        List<SpecializationData> specializations = node.getSpecializations();
+        for (int i = 0; i < specializations.size(); i++) {
+            SpecializationData cur = specializations.get(i);
+            if (cur.getExceptions().isEmpty()) {
+                continue;
+            }
+            SpecializationData next = i + 1 < specializations.size() ? specializations.get(i + 1) : null;
+
+            if (!cur.isContainedBy(next)) {
+                // error should be able to contain
+                next.addError("This specialiation is not a valid exceptional rewrite target for %s. To fix this make %s compatible to %s or remove the exceptional rewrite.",
+                                cur.createReferenceName(), next.createReferenceName(), cur.createReferenceName());
+                continue;
+            }
+            if (!next.getContains().contains(cur)) {
+                next.getContains().add(cur);
+                // TODO resolve transitive contains
+            }
+        }
+
+        for (SpecializationData cur : specializations) {
+            if (cur.getExceptions().isEmpty()) {
+                continue;
+            }
+            for (SpecializationData child : specializations) {
+                if (child != null && child != cur && child.getContains().contains(cur)) {
+                    cur.getExcludedBy().add(child);
+                }
+            }
+        }
+    }
+
+    private static void initializeContains(NodeData node) {
+        for (SpecializationData specialization : node.getSpecializations()) {
+            Set<SpecializationData> resolvedSpecializations = specialization.getContains();
+            resolvedSpecializations.clear();
+            Set<String> includeNames = specialization.getContainsNames();
+            for (String includeName : includeNames) {
+                // TODO reduce complexity of this lookup.
+                SpecializationData foundSpecialization = lookupSpecialization(node, includeName);
+
+                if (foundSpecialization == null) {
+                    AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
+                    specialization.addError(value, "The referenced specialization '%s' could not be found.", includeName);
+                } else {
+                    if (!foundSpecialization.isContainedBy(specialization)) {
+                        AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
+                        if (foundSpecialization.compareTo(specialization) > 0) {
+                            specialization.addError(value, "The contained specialization '%s' must be declared before the containing specialization.", includeName);
+                        } else {
+                            specialization.addError(value,
+                                            "The contained specialization '%s' is not fully compatible. The contained specialization must be strictly more generic than the containing one.",
+                                            includeName);
+                        }
+
+                    }
+                    resolvedSpecializations.add(foundSpecialization);
+                }
+            }
+        }
+    }
+
+    private void resolveContains(NodeData node) {
+        // flatten transitive includes
+        for (SpecializationData specialization : node.getSpecializations()) {
+            if (specialization.getContains().isEmpty()) {
+                continue;
+            }
+            Set<SpecializationData> foundSpecializations = new HashSet<>();
+            collectIncludes(specialization, foundSpecializations, new HashSet<SpecializationData>());
+            specialization.getContains().addAll(foundSpecializations);
+        }
+    }
+
+    private static SpecializationData lookupSpecialization(NodeData node, String includeName) {
+        SpecializationData foundSpecialization = null;
+        for (SpecializationData searchSpecialization : node.getSpecializations()) {
+            if (searchSpecialization.getMethodName().equals(includeName)) {
+                foundSpecialization = searchSpecialization;
+                break;
+            }
+        }
+        return foundSpecialization;
+    }
+
+    private void collectIncludes(SpecializationData specialization, Set<SpecializationData> found, Set<SpecializationData> visited) {
+        if (visited.contains(specialization)) {
+            // circle found
+            specialization.addError("Circular contained specialization '%s' found.", specialization.createReferenceName());
+            return;
+        }
+        visited.add(specialization);
+
+        for (SpecializationData included : specialization.getContains()) {
+            collectIncludes(included, found, new HashSet<>(visited));
+            found.add(included);
+        }
+    }
+
+    private static void initializeReachability(final NodeData node) {
+        List<SpecializationData> specializations = node.getSpecializations();
+        for (int i = specializations.size() - 1; i >= 0; i--) {
+            SpecializationData current = specializations.get(i);
+            if (current.isPolymorphic()) {
+                current.setReachable(true);
+                continue;
+            }
+
+            List<SpecializationData> shadowedBy = null;
+            for (int j = i - 1; j >= 0; j--) {
+                SpecializationData prev = specializations.get(j);
+                if (prev.isPolymorphic()) {
+                    continue;
+                }
+                if (!current.isReachableAfter(prev)) {
+                    if (shadowedBy == null) {
+                        shadowedBy = new ArrayList<>();
+                    }
+                    shadowedBy.add(prev);
+                }
+            }
+
+            if (shadowedBy != null) {
+                StringBuilder name = new StringBuilder();
+                String sep = "";
+                for (SpecializationData shadowSpecialization : shadowedBy) {
+                    name.append(sep);
+                    name.append(shadowSpecialization.createReferenceName());
+                    sep = ", ";
+                }
+                current.addError("%s is not reachable. It is shadowed by %s.", current.isGeneric() ? "Generic" : "Specialization", name);
+            }
+            current.setReachable(shadowedBy == null);
+        }
+    }
+
+    private static List<String> initializeSpecializationIds(List<SpecializationData> specializations) {
+        int lastSize = -1;
+        List<List<String>> signatureChunks = new ArrayList<>();
+        for (SpecializationData other : specializations) {
+            if (!other.isSpecialized()) {
+                continue;
+            }
+            List<String> paramIds = new LinkedList<>();
+            paramIds.add(ElementUtils.getTypeId(other.getReturnType().getType()));
+            for (Parameter param : other.getParameters()) {
+                if (param.getSpecification().getExecution() == null) {
+                    continue;
+                }
+                paramIds.add(ElementUtils.getTypeId(param.getType()));
+            }
+            assert lastSize == -1 || lastSize == paramIds.size();
+            if (lastSize != -1 && lastSize != paramIds.size()) {
+                throw new AssertionError();
+            }
+            signatureChunks.add(paramIds);
+            lastSize = paramIds.size();
+        }
+
+        // reduce id vertically
+        for (int i = 0; i < lastSize; i++) {
+            String prev = null;
+            boolean allSame = true;
+            for (List<String> signature : signatureChunks) {
+                String arg = signature.get(i);
+                if (prev == null) {
+                    prev = arg;
+                    continue;
+                } else if (!prev.equals(arg)) {
+                    allSame = false;
+                    break;
+                }
+                prev = arg;
+            }
+
+            if (allSame) {
+                for (List<String> signature : signatureChunks) {
+                    signature.remove(i);
+                }
+                lastSize--;
+            }
+        }
+
+        // reduce id horizontally
+        for (List<String> signature : signatureChunks) {
+            if (signature.isEmpty()) {
+                continue;
+            }
+            String prev = null;
+            boolean allSame = true;
+            for (String arg : signature) {
+                if (prev == null) {
+                    prev = arg;
+                    continue;
+                } else if (!prev.equals(arg)) {
+                    allSame = false;
+                    break;
+                }
+                prev = arg;
+            }
+
+            if (allSame) {
+                signature.clear();
+                signature.add(prev);
+            }
+        }
+
+        // create signatures
+        List<String> signatures = new ArrayList<>();
+        for (List<String> signatureChunk : signatureChunks) {
+            StringBuilder b = new StringBuilder();
+            if (signatureChunk.isEmpty()) {
+                b.append("Default");
+            } else {
+                for (String s : signatureChunk) {
+                    b.append(s);
+                }
+            }
+            signatures.add(b.toString());
+        }
+
+        Map<String, Integer> counts = new HashMap<>();
+        for (String s1 : signatures) {
+            Integer count = counts.get(s1);
+            if (count == null) {
+                count = 0;
+            }
+            count++;
+            counts.put(s1, count);
+        }
+
+        for (String s : counts.keySet()) {
+            int count = counts.get(s);
+            if (count > 1) {
+                int number = 0;
+                for (ListIterator<String> iterator = signatures.listIterator(); iterator.hasNext();) {
+                    String s2 = iterator.next();
+                    if (s.equals(s2)) {
+                        iterator.set(s2 + number);
+                        number++;
+                    }
+                }
+            }
+        }
+
+        return signatures;
+    }
+
+    private void initializeGuards(List<? extends Element> elements, NodeData node) {
+        Map<String, List<GuardData>> guards = new HashMap<>();
+        for (SpecializationData specialization : node.getSpecializations()) {
+            for (GuardExpression exp : specialization.getGuards()) {
+                guards.put(exp.getGuardName(), null);
+            }
+        }
+
+        GuardParser parser = new GuardParser(context, node, null, guards.keySet());
+        List<GuardData> resolvedGuards = parser.parse(elements);
+        for (GuardData guard : resolvedGuards) {
+            List<GuardData> groupedGuards = guards.get(guard.getMethodName());
+            if (groupedGuards == null) {
+                groupedGuards = new ArrayList<>();
+                guards.put(guard.getMethodName(), groupedGuards);
+            }
+            groupedGuards.add(guard);
+        }
+
+        for (SpecializationData specialization : node.getSpecializations()) {
+            for (GuardExpression exp : specialization.getGuards()) {
+                resolveGuardExpression(node, specialization, guards, exp);
+            }
+        }
+    }
+
+    private void resolveGuardExpression(NodeData node, TemplateMethod source, Map<String, List<GuardData>> guards, GuardExpression expression) {
+        List<GuardData> availableGuards = guards.get(expression.getGuardName());
+        if (availableGuards == null) {
+            source.addError("No compatible guard with method name '%s' found. Please note that all signature types of the method guard must be declared in the type system.", expression.getGuardName());
+            return;
+        }
+        List<ExecutableElement> guardMethods = new ArrayList<>();
+        for (GuardData guard : availableGuards) {
+            guardMethods.add(guard.getMethod());
+        }
+        GuardParser parser = new GuardParser(context, node, source, new HashSet<>(Arrays.asList(expression.getGuardName())));
+        List<GuardData> matchingGuards = parser.parse(guardMethods);
+        if (!matchingGuards.isEmpty()) {
+            GuardData guard = matchingGuards.get(0);
+            // use the shared instance of the guard data
+            for (GuardData guardData : availableGuards) {
+                if (guardData.getMethod() == guard.getMethod()) {
+                    expression.setGuard(guardData);
+                    return;
+                }
+            }
+            throw new AssertionError("Should not reach here.");
+        } else {
+            MethodSpec spec = parser.createSpecification(source.getMethod(), source.getMarkerAnnotation());
+            spec.applyTypeDefinitions("types");
+            source.addError("No guard with name '%s' matched the required signature. Expected signature: %n%s", expression.getGuardName(), spec.toSignatureString("guard"));
+        }
+    }
+
+    private void initializeGeneric(final NodeData node) {
+        if (!node.needsRewrites(context)) {
+            return;
+        }
+
+        List<SpecializationData> generics = new ArrayList<>();
+        for (SpecializationData spec : node.getSpecializations()) {
+            if (spec.isGeneric()) {
+                generics.add(spec);
+            }
+        }
+
+        if (generics.size() == 1 && node.getSpecializations().size() == 1) {
+            // TODO this limitation should be lifted
+            for (SpecializationData generic : generics) {
+                generic.addError("@%s defined but no @%s.", Generic.class.getSimpleName(), Specialization.class.getSimpleName());
+            }
+        }
+
+        if (generics.isEmpty()) {
+            node.getSpecializations().add(createGenericSpecialization(node));
+        } else {
+            if (generics.size() > 1) {
+                for (SpecializationData generic : generics) {
+                    generic.addError("Only @%s is allowed per operation.", Generic.class.getSimpleName());
+                }
+            }
+        }
+    }
+
+    private SpecializationData createGenericSpecialization(final NodeData node) {
+        GenericParser parser = new GenericParser(context, node);
+        MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null);
+
+        List<TypeMirror> parameterTypes = new ArrayList<>();
+        int signatureIndex = 1;
+        for (ParameterSpec spec : specification.getRequired()) {
+            parameterTypes.add(createGenericType(spec, node.getSpecializations(), signatureIndex));
+            if (spec.isSignature()) {
+                signatureIndex++;
+            }
+        }
+
+        TypeMirror returnType = createGenericType(specification.getReturnType(), node.getSpecializations(), 0);
+        SpecializationData generic = parser.create("Generic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, parameterTypes);
+        if (generic == null) {
+            throw new RuntimeException("Unable to create generic signature for node " + node.getNodeId() + " with " + parameterTypes + ". Specification " + specification + ".");
+        }
+
+        return generic;
+    }
+
+    private TypeMirror createGenericType(ParameterSpec spec, List<SpecializationData> specializations, int signatureIndex) {
+        NodeExecutionData execution = spec.getExecution();
+        if (execution == null) {
+            if (spec.getAllowedTypes().size() == 1) {
+                return spec.getAllowedTypes().get(0);
+            } else {
+                return ElementUtils.getCommonSuperType(context, spec.getAllowedTypes().toArray(new TypeMirror[0]));
+            }
+        } else {
+            Set<TypeData> types = new HashSet<>();
+            for (SpecializationData specialization : specializations) {
+                types.add(specialization.getTypeSignature().get(signatureIndex));
+            }
+
+            NodeChildData child = execution.getChild();
+            TypeData genericType = null;
+            if (types.size() == 1) {
+                ExecutableTypeData executable = child.findExecutableType(context, types.iterator().next());
+                if (executable != null && (signatureIndex == 0 || !executable.hasUnexpectedValue(context))) {
+                    genericType = types.iterator().next();
+                }
+            }
+            if (genericType == null) {
+                genericType = child.findAnyGenericExecutableType(context).getType();
+            }
+            return genericType.getPrimitiveType();
+        }
+    }
+
+    private static void initializeUninitialized(final NodeData node) {
+        SpecializationData generic = node.getGenericSpecialization();
+        if (generic == null) {
+            return;
+        }
+        for (Parameter parameter : generic.getReturnTypeAndParameters()) {
+            if (ElementUtils.isObject(parameter.getType())) {
+                continue;
+            }
+            Set<String> types = new HashSet<>();
+            for (SpecializationData specialization : node.getSpecializations()) {
+                Parameter actualParameter = specialization.findParameter(parameter.getLocalName());
+                if (actualParameter != null) {
+                    types.add(ElementUtils.getQualifiedName(actualParameter.getType()));
+                }
+            }
+            if (types.size() > 1) {
+                generic.replaceParameter(parameter.getLocalName(), new Parameter(parameter, node.getTypeSystem().getGenericTypeData()));
+            }
+        }
+        TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", -1, node, generic.getSpecification(), null, null, generic.getReturnType(), generic.getParameters());
+        // should not use messages from generic specialization
+        uninializedMethod.getMessages().clear();
+        node.getSpecializations().add(new SpecializationData(node, uninializedMethod, SpecializationKind.UNINITIALIZED));
+    }
+
+    private void initializePolymorphism(NodeData node) {
+        if (!node.needsRewrites(context)) {
+            return;
+        }
+
+        SpecializationData generic = node.getGenericSpecialization();
+
+        List<TypeData> polymorphicSignature = new ArrayList<>();
+        List<Parameter> updatePolymorphic = Arrays.asList();
+        for (Parameter genericParameter : updatePolymorphic) {
+            if (!genericParameter.getSpecification().isSignature()) {
+                continue;
+            }
+
+            Set<TypeData> usedTypes = new HashSet<>();
+            for (SpecializationData specialization : node.getSpecializations()) {
+                if (!specialization.isSpecialized()) {
+                    continue;
+                }
+                Parameter parameter = specialization.findParameter(genericParameter.getLocalName());
+                if (parameter == null) {
+                    throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName());
+                }
+                usedTypes.add(parameter.getTypeSystemType());
+            }
+
+            TypeData polymorphicType;
+            if (usedTypes.size() == 1) {
+                polymorphicType = usedTypes.iterator().next();
+            } else {
+                polymorphicType = node.getTypeSystem().getGenericTypeData();
+            }
+            polymorphicSignature.add(polymorphicType);
+        }
+
+        SpecializationData polymorphic = new SpecializationData(node, generic, SpecializationKind.POLYMORPHIC);
+        polymorphic.updateSignature(new TypeSignature(polymorphicSignature));
+        node.getSpecializations().add(polymorphic);
+    }
+
+    private void initializeShortCircuits(NodeData node) {
+        Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
+
+        boolean valid = true;
+        List<NodeExecutionData> shortCircuitExecutions = new ArrayList<>();
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (!execution.isShortCircuit()) {
+                continue;
+            }
+            shortCircuitExecutions.add(execution);
+            String valueName = execution.getShortCircuitId();
+            List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
+
+            if (availableCircuits == null || availableCircuits.isEmpty()) {
+                node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
+                valid = false;
+                continue;
+            }
+
+            boolean sameMethodName = true;
+            String methodName = availableCircuits.get(0).getMethodName();
+            for (ShortCircuitData circuit : availableCircuits) {
+                if (!circuit.getMethodName().equals(methodName)) {
+                    sameMethodName = false;
+                }
+            }
+
+            if (!sameMethodName) {
+                for (ShortCircuitData circuit : availableCircuits) {
+                    circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName);
+                }
+                valid = false;
+                continue;
+            }
+
+            ShortCircuitData genericCircuit = null;
+            for (ShortCircuitData circuit : availableCircuits) {
+                if (isGenericShortCutMethod(circuit)) {
+                    genericCircuit = circuit;
+                    break;
+                }
+            }
+
+            if (genericCircuit == null) {
+                node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
+                valid = false;
+                continue;
+            }
+
+            for (ShortCircuitData circuit : availableCircuits) {
+                if (circuit != genericCircuit) {
+                    circuit.setGenericShortCircuitMethod(genericCircuit);
+                }
+            }
+        }
+
+        if (!valid) {
+            return;
+        }
+
+        List<SpecializationData> specializations = new ArrayList<>();
+        specializations.addAll(node.getSpecializations());
+        for (SpecializationData specialization : specializations) {
+            List<ShortCircuitData> assignedShortCuts = new ArrayList<>(shortCircuitExecutions.size());
+
+            for (NodeExecutionData shortCircuit : shortCircuitExecutions) {
+                List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(shortCircuit.getShortCircuitId());
+
+                ShortCircuitData genericShortCircuit = null;
+                ShortCircuitData compatibleShortCircuit = null;
+                for (ShortCircuitData circuit : availableShortCuts) {
+                    if (circuit.isGeneric()) {
+                        genericShortCircuit = circuit;
+                    } else if (circuit.isCompatibleTo(specialization)) {
+                        compatibleShortCircuit = circuit;
+                    }
+                }
+
+                if (compatibleShortCircuit == null) {
+                    compatibleShortCircuit = genericShortCircuit;
+                }
+                assignedShortCuts.add(compatibleShortCircuit);
+            }
+            specialization.setShortCircuits(assignedShortCuts);
+        }
+    }
+
+    private boolean isGenericShortCutMethod(ShortCircuitData method) {
+        for (Parameter parameter : method.getParameters()) {
+            NodeExecutionData execution = parameter.getSpecification().getExecution();
+            if (execution == null) {
+                continue;
+            }
+            ExecutableTypeData found = null;
+            List<ExecutableTypeData> executableElements = execution.getChild().findGenericExecutableTypes(context);
+            for (ExecutableTypeData executable : executableElements) {
+                if (executable.getType().equalsType(parameter.getTypeSystemType())) {
+                    found = executable;
+                    break;
+                }
+            }
+            if (found == null) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static Map<String, List<ShortCircuitData>> groupShortCircuits(List<ShortCircuitData> shortCircuits) {
+        Map<String, List<ShortCircuitData>> group = new HashMap<>();
+        for (ShortCircuitData shortCircuit : shortCircuits) {
+            List<ShortCircuitData> circuits = group.get(shortCircuit.getValueName());
+            if (circuits == null) {
+                circuits = new ArrayList<>();
+                group.put(shortCircuit.getValueName(), circuits);
+            }
+            circuits.add(shortCircuit);
+        }
+        return group;
+    }
+
+    private static boolean verifySpecializationSameLength(NodeData nodeData) {
+        int lastArgs = -1;
+        for (SpecializationData specializationData : nodeData.getSpecializations()) {
+            int signatureArgs = specializationData.getSignatureSize();
+            if (lastArgs == signatureArgs) {
+                continue;
+            }
+            if (lastArgs != -1) {
+                for (SpecializationData specialization : nodeData.getSpecializations()) {
+                    specialization.addError("All specializations must have the same number of arguments.");
+                }
+                return false;
+            } else {
+                lastArgs = signatureArgs;
+            }
+        }
+        return true;
+    }
+
+    private static void verifyVisibilities(NodeData node) {
+        if (node.getTemplateType().getModifiers().contains(Modifier.PRIVATE) && node.getSpecializations().size() > 0) {
+            node.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName());
+        }
+    }
+
+    private static void verifyMissingAbstractMethods(NodeData nodeData, List<? extends Element> originalElements) {
+        if (!nodeData.needsFactory()) {
+            // missing abstract methods only needs to be implemented
+            // if we need go generate factory for it.
+            return;
+        }
+
+        List<Element> elements = new ArrayList<>(originalElements);
+        Set<Element> unusedElements = new HashSet<>(elements);
+        for (TemplateMethod method : nodeData.getAllTemplateMethods()) {
+            unusedElements.remove(method.getMethod());
+        }
+
+        for (NodeFieldData field : nodeData.getFields()) {
+            if (field.getGetter() != null) {
+                unusedElements.remove(field.getGetter());
+            }
+        }
+
+        for (NodeChildData child : nodeData.getChildren()) {
+            if (child.getAccessElement() != null) {
+                unusedElements.remove(child.getAccessElement());
+            }
+        }
+
+        for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) {
+            if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) {
+                nodeData.addError("The type %s must implement the inherited abstract method %s.", ElementUtils.getSimpleName(nodeData.getTemplateType()),
+                                ElementUtils.getReadableSignature(unusedMethod));
+            }
+        }
+    }
+
+    private static void verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) {
+        for (int i = 0; i < methods.size(); i++) {
+            TemplateMethod m1 = methods.get(i);
+            if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
+                m1.addError("Naming convention: method name must start with '%s'.", prefix);
+            }
+        }
+    }
+
+    private static void verifySpecializationThrows(NodeData node) {
+        Map<String, SpecializationData> specializationMap = new HashMap<>();
+        for (SpecializationData spec : node.getSpecializations()) {
+            specializationMap.put(spec.getMethodName(), spec);
+        }
+        for (SpecializationData sourceSpecialization : node.getSpecializations()) {
+            if (sourceSpecialization.getExceptions() != null) {
+                for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) {
+                    for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) {
+                        if (otherThrowsData != throwsData && ElementUtils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) {
+                            throwsData.addError("Duplicate exception type.");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private void verifyConstructors(NodeData nodeData) {
+        if (!nodeData.needsRewrites(context)) {
+            // no specialization constructor is needed if the node never rewrites.
+            return;
+        }
+
+        TypeElement type = ElementUtils.fromTypeMirror(nodeData.getNodeType());
+        List<ExecutableElement> constructors = ElementFilter.constructorsIn(type.getEnclosedElements());
+
+        boolean parametersFound = false;
+        for (ExecutableElement constructor : constructors) {
+            if (!constructor.getParameters().isEmpty() && !isSourceSectionConstructor(context, constructor)) {
+                parametersFound = true;
+            }
+        }
+        if (!parametersFound) {
+            return;
+        }
+        for (ExecutableElement e : constructors) {
+            if (e.getParameters().size() == 1) {
+                TypeMirror firstArg = e.getParameters().get(0).asType();
+                if (ElementUtils.typeEquals(firstArg, nodeData.getNodeType())) {
+                    if (e.getModifiers().contains(Modifier.PRIVATE)) {
+                        nodeData.addError("The specialization constructor must not be private.");
+                    } else if (constructors.size() <= 1) {
+                        nodeData.addError("The specialization constructor must not be the only constructor. The definition of an alternative constructor is required.");
+                    }
+                    return;
+                }
+            }
+        }
+
+        // not found
+        nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", ElementUtils.getSimpleName(type), ElementUtils.getSimpleName(type));
+    }
+
+    public static boolean isSourceSectionConstructor(ProcessorContext context, ExecutableElement constructor) {
+        return constructor.getParameters().size() == 1 && ElementUtils.typeEquals(constructor.getParameters().get(0).asType(), context.getTruffleTypes().getSourceSection());
+    }
+
+    private AnnotationMirror findFirstAnnotation(List<? extends Element> elements, Class<? extends Annotation> annotation) {
+        for (Element element : elements) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, element, annotation);
+            if (mirror != null) {
+                return mirror;
+            }
+        }
+        return null;
+    }
+
+    private TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) {
+        TypeMirror inhertNodeType = context.getTruffleTypes().getNode();
+        TypeMirror value = ElementUtils.getAnnotationValue(TypeMirror.class, annotation, valueName);
+        if (ElementUtils.typeEquals(inhertNodeType, value)) {
+            return parentType;
+        } else {
+            return value;
+        }
+    }
+
+    private ExecutableElement findGetter(List<? extends Element> elements, String variableName, TypeMirror type) {
+        if (type == null) {
+            return null;
+        }
+        String methodName;
+        if (ElementUtils.typeEquals(type, context.getType(boolean.class))) {
+            methodName = "is" + ElementUtils.firstLetterUpperCase(variableName);
+        } else {
+            methodName = "get" + ElementUtils.firstLetterUpperCase(variableName);
+        }
+
+        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+            if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && ElementUtils.isAssignable(type, method.getReturnType())) {
+                return method;
+            }
+        }
+        return null;
+    }
+
+    private static List<TypeElement> collectSuperClasses(List<TypeElement> collection, TypeElement element) {
+        if (element != null) {
+            collection.add(element);
+            if (element.getSuperclass() != null) {
+                collectSuperClasses(collection, ElementUtils.fromTypeMirror(element.getSuperclass()));
+            }
+        }
+        return collection;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ShortCircuitParser.java	Mon Aug 11 15:57:14 2014 +0200
@@ -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.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class ShortCircuitParser extends NodeMethodParser<ShortCircuitData> {
+
+    private final Set<String> shortCircuitValues;
+
+    public ShortCircuitParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+
+        shortCircuitValues = new HashSet<>();
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (execution.isShortCircuit()) {
+                shortCircuitValues.add(execution.getShortCircuitId());
+            }
+        }
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        String shortCircuitValue = ElementUtils.getAnnotationValue(String.class, mirror, "value");
+
+        return createDefaultMethodSpec(method, mirror, true, shortCircuitValue);
+    }
+
+    @Override
+    protected ParameterSpec createReturnParameterSpec() {
+        return new ParameterSpec("has", getContext().getType(boolean.class));
+    }
+
+    @Override
+    public ShortCircuitData create(TemplateMethod method, boolean invalid) {
+        String shortCircuitValue = ElementUtils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value");
+
+        if (!shortCircuitValues.contains(shortCircuitValue)) {
+            method.addError("Invalid short circuit value %s.", 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.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.util.*;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature;
+
+/**
+ * Class creates groups of specializations to optimize the layout of generated executeAndSpecialize
+ * and generic execute methods.
+ */
+public final class SpecializationGroup {
+
+    private final List<String> assumptions;
+    private final List<TypeGuard> typeGuards;
+    private final List<GuardExpression> guards;
+
+    private final NodeData node;
+    private final SpecializationData specialization;
+    private final List<SpecializationGroup> children = new ArrayList<>();
+
+    private SpecializationGroup parent;
+
+    private SpecializationGroup(SpecializationData data) {
+        this.node = data.getNode();
+        this.assumptions = new ArrayList<>();
+        this.typeGuards = new ArrayList<>();
+        this.guards = new ArrayList<>();
+        this.specialization = data;
+
+        this.assumptions.addAll(data.getAssumptions());
+        TypeSignature sig = data.getTypeSignature();
+        for (int i = 1; i < sig.size(); i++) {
+            typeGuards.add(new TypeGuard(sig.get(i), i - 1));
+        }
+        this.guards.addAll(data.getGuards());
+    }
+
+    public SpecializationGroup(List<SpecializationGroup> children, List<String> assumptionMatches, List<TypeGuard> typeGuardsMatches, List<GuardExpression> guardMatches) {
+        assert !children.isEmpty() : "children must not be empty";
+        this.assumptions = assumptionMatches;
+        this.typeGuards = typeGuardsMatches;
+        this.guards = guardMatches;
+        this.node = children.get(0).node;
+        this.specialization = null;
+        updateChildren(children);
+    }
+
+    public List<TypeGuard> getAllGuards() {
+        List<TypeGuard> collectedGuards = new ArrayList<>();
+        collectedGuards.addAll(typeGuards);
+        if (parent != null) {
+            collectedGuards.addAll(parent.getAllGuards());
+        }
+        return collectedGuards;
+    }
+
+    public TypeGuard findTypeGuard(int signatureIndex) {
+        for (TypeGuard guard : typeGuards) {
+            if (guard.getSignatureIndex() == signatureIndex) {
+                return guard;
+            }
+        }
+        return null;
+    }
+
+    public List<GuardExpression> findElseConnectableGuards() {
+        if (!getTypeGuards().isEmpty() || !getAssumptions().isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        if (getGuards().isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        List<GuardExpression> elseConnectableGuards = new ArrayList<>();
+        int guardIndex = 0;
+        while (guardIndex < getGuards().size() && findNegatedGuardInPrevious(getGuards().get(guardIndex)) != null) {
+            elseConnectableGuards.add(getGuards().get(guardIndex));
+            guardIndex++;
+        }
+
+        return elseConnectableGuards;
+    }
+
+    private GuardExpression findNegatedGuardInPrevious(GuardExpression guard) {
+        SpecializationGroup previous = this.getPreviousGroup();
+        if (previous == null) {
+            return null;
+        }
+        List<GuardExpression> elseConnectedGuards = previous.findElseConnectableGuards();
+
+        if (previous == null || previous.getGuards().size() != elseConnectedGuards.size() + 1) {
+            return null;
+        }
+
+        /* Guard is else branch can be connected in previous specialization. */
+        if (elseConnectedGuards.contains(guard)) {
+            return guard;
+        }
+
+        GuardExpression previousGuard = previous.getGuards().get(elseConnectedGuards.size());
+        if (guard.getResolvedGuard().getMethod().equals(previousGuard.getResolvedGuard().getMethod()) && guard.isNegated() != previousGuard.isNegated()) {
+            return guard;
+        }
+        return null;
+    }
+
+    private void updateChildren(List<SpecializationGroup> childs) {
+        if (!children.isEmpty()) {
+            children.clear();
+        }
+        this.children.addAll(childs);
+        for (SpecializationGroup child : childs) {
+            child.parent = this;
+        }
+    }
+
+    public SpecializationGroup getParent() {
+        return parent;
+    }
+
+    public List<String> getAssumptions() {
+        return assumptions;
+    }
+
+    public List<TypeGuard> getTypeGuards() {
+        return typeGuards;
+    }
+
+    public List<GuardExpression> getGuards() {
+        return guards;
+    }
+
+    public List<SpecializationGroup> getChildren() {
+        return children;
+    }
+
+    public SpecializationData getSpecialization() {
+        return specialization;
+    }
+
+    private static SpecializationGroup combine(List<SpecializationGroup> groups) {
+        if (groups.isEmpty()) {
+            throw new IllegalArgumentException("empty combinations");
+        }
+        if (groups.size() == 1) {
+            return null;
+        }
+
+        List<String> assumptionMatches = new ArrayList<>();
+        List<TypeGuard> typeGuardsMatches = new ArrayList<>();
+        List<GuardExpression> guardMatches = new ArrayList<>();
+
+        SpecializationGroup first = groups.get(0);
+        List<SpecializationGroup> others = groups.subList(1, groups.size());
+
+        outer: for (String assumption : first.assumptions) {
+            for (SpecializationGroup other : others) {
+                if (!other.assumptions.contains(assumption)) {
+                    // assumptions can be combined unordered
+                    continue outer;
+                }
+            }
+            assumptionMatches.add(assumption);
+        }
+
+        outer: for (TypeGuard typeGuard : first.typeGuards) {
+            for (SpecializationGroup other : others) {
+                if (!other.typeGuards.contains(typeGuard)) {
+                    // type guards can be combined unordered
+                    continue outer;
+                }
+            }
+            typeGuardsMatches.add(typeGuard);
+        }
+
+        outer: for (GuardExpression guard : first.guards) {
+            for (SpecializationGroup other : others) {
+                if (!other.guards.contains(guard)) {
+                    // we must break here. One guard may depend on the other.
+                    break outer;
+                }
+            }
+            guardMatches.add(guard);
+        }
+
+        // check for guards for required type casts
+        for (Iterator<GuardExpression> iterator = guardMatches.iterator(); iterator.hasNext();) {
+            GuardExpression guardMatch = iterator.next();
+
+            int signatureIndex = 0;
+            for (Parameter parameter : guardMatch.getResolvedGuard().getParameters()) {
+                signatureIndex++;
+                if (!parameter.getSpecification().isSignature()) {
+                    continue;
+                }
+
+                TypeMirror guardType = parameter.getType();
+
+                // object guards can be safely moved up
+                if (ElementUtils.isObject(guardType)) {
+                    continue;
+                }
+
+                // generic guards can be safely moved up
+                SpecializationData generic = first.node.getGenericSpecialization();
+                if (generic != null) {
+                    Parameter genericParameter = generic.findParameter(parameter.getLocalName());
+                    if (genericParameter != null && ElementUtils.typeEquals(genericParameter.getType(), guardType)) {
+                        continue;
+                    }
+                }
+
+                // signature index required for moving up guards
+                if (containsIndex(typeGuardsMatches, signatureIndex) || (first.getParent() != null && first.getParent().containsTypeGuardIndex(signatureIndex))) {
+                    continue;
+                }
+
+                iterator.remove();
+                break;
+            }
+        }
+
+        if (assumptionMatches.isEmpty() && typeGuardsMatches.isEmpty() && guardMatches.isEmpty()) {
+            return null;
+        }
+
+        for (SpecializationGroup group : groups) {
+            group.assumptions.removeAll(assumptionMatches);
+            group.typeGuards.removeAll(typeGuardsMatches);
+            group.guards.removeAll(guardMatches);
+        }
+
+        List<SpecializationGroup> newChildren = new ArrayList<>(groups);
+        return new SpecializationGroup(newChildren, assumptionMatches, typeGuardsMatches, guardMatches);
+    }
+
+    private boolean containsTypeGuardIndex(int index) {
+        if (containsIndex(typeGuards, index)) {
+            return true;
+        }
+        if (parent != null) {
+            return parent.containsTypeGuardIndex(index);
+        }
+        return false;
+    }
+
+    private static boolean containsIndex(List<TypeGuard> typeGuards, int signatureIndex) {
+        for (TypeGuard guard : typeGuards) {
+            if (guard.signatureIndex == signatureIndex) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static SpecializationGroup create(SpecializationData specialization) {
+        return new SpecializationGroup(specialization);
+    }
+
+    public static SpecializationGroup create(List<SpecializationData> specializations) {
+        List<SpecializationGroup> groups = new ArrayList<>();
+        for (SpecializationData specialization : specializations) {
+            groups.add(new SpecializationGroup(specialization));
+        }
+        return new SpecializationGroup(createCombinationalGroups(groups), Collections.<String> emptyList(), Collections.<TypeGuard> emptyList(), Collections.<GuardExpression> emptyList());
+    }
+
+    @Override
+    public String toString() {
+        return "SpecializationGroup [assumptions=" + assumptions + ", typeGuards=" + typeGuards + ", guards=" + guards + "]";
+    }
+
+    private static List<SpecializationGroup> createCombinationalGroups(List<SpecializationGroup> groups) {
+        if (groups.size() <= 1) {
+            return groups;
+        }
+        List<SpecializationGroup> newGroups = new ArrayList<>();
+
+        int i = 0;
+        for (i = 0; i < groups.size();) {
+            SpecializationGroup combined = null;
+            for (int j = groups.size(); j > i + 1; j--) {
+                combined = combine(groups.subList(i, j));
+                if (combined != null) {
+                    break;
+                }
+            }
+            SpecializationGroup newGroup;
+            if (combined == null) {
+                newGroup = groups.get(i);
+                i++;
+            } else {
+                newGroup = combined;
+                List<SpecializationGroup> originalGroups = new ArrayList<>(combined.children);
+                combined.updateChildren(createCombinationalGroups(originalGroups));
+                i += originalGroups.size();
+            }
+
+            newGroups.add(newGroup);
+
+        }
+
+        return newGroups;
+    }
+
+    public SpecializationGroup getPreviousGroup() {
+        if (parent == null || parent.children.isEmpty()) {
+            return null;
+        }
+        int index = parent.children.indexOf(this);
+        if (index <= 0) {
+            return null;
+        }
+        return parent.children.get(index - 1);
+    }
+
+    public int getUncheckedSpecializationIndex() {
+        int groupMaxIndex = getMaxSpecializationIndex();
+
+        int genericIndex = node.getSpecializations().indexOf(node.getGenericSpecialization());
+        if (groupMaxIndex >= genericIndex) {
+            // no minimum state check for an generic index
+            groupMaxIndex = -1;
+        }
+
+        if (groupMaxIndex > -1) {
+            // no minimum state check if already checked by parent group
+            int parentMaxIndex = -1;
+            if (getParent() != null) {
+                parentMaxIndex = getParent().getMaxSpecializationIndex();
+            }
+            if (groupMaxIndex == parentMaxIndex) {
+                groupMaxIndex = -1;
+            }
+        }
+        return groupMaxIndex;
+    }
+
+    public int getMaxSpecializationIndex() {
+        if (specialization != null) {
+            return specialization.getNode().getSpecializations().indexOf(specialization);
+        } else {
+            int max = Integer.MIN_VALUE;
+            for (SpecializationGroup childGroup : getChildren()) {
+                max = Math.max(max, childGroup.getMaxSpecializationIndex());
+            }
+            return max;
+        }
+    }
+
+    public static final class TypeGuard {
+
+        private final int signatureIndex;
+        private final TypeData type;
+
+        public TypeGuard(TypeData type, int signatureIndex) {
+            this.type = type;
+            this.signatureIndex = signatureIndex;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + signatureIndex;
+            result = prime * result + type.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            } else if (obj == null) {
+                return false;
+            } else if (getClass() != obj.getClass()) {
+                return false;
+            }
+
+            TypeGuard other = (TypeGuard) obj;
+            if (signatureIndex != other.signatureIndex) {
+                return false;
+            } else if (!type.equals(other.type)) {
+                return false;
+            }
+            return true;
+        }
+
+        public int getSignatureIndex() {
+            return signatureIndex;
+        }
+
+        public TypeData getType() {
+            return type;
+        }
+    }
+
+    public boolean isTypeGuardUsedInAnyGuardBelow(ProcessorContext context, SpecializationData source, TypeGuard typeGuard) {
+
+        for (GuardExpression guard : guards) {
+            Parameter guardParameter = guard.getResolvedGuard().getSignatureParameter(typeGuard.getSignatureIndex());
+            if (guardParameter == null) {
+                // guardParameters are optional
+                continue;
+            }
+            Parameter sourceParameter = source.getSignatureParameter(typeGuard.getSignatureIndex());
+            if (sourceParameter.getTypeSystemType().needsCastTo(guardParameter.getType())) {
+                return true;
+            }
+        }
+
+        for (SpecializationGroup group : getChildren()) {
+            if (group.isTypeGuardUsedInAnyGuardBelow(context, source, typeGuard)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind;
+
+public class SpecializationMethodParser extends NodeMethodParser<SpecializationData> {
+
+    public SpecializationMethodParser(ProcessorContext context, NodeData operation) {
+        super(context, operation);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        return createDefaultMethodSpec(method, mirror, true, null);
+    }
+
+    @Override
+    public SpecializationData create(TemplateMethod method, boolean invalid) {
+        return parseSpecialization(method);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return Specialization.class;
+    }
+
+    private SpecializationData parseSpecialization(TemplateMethod method) {
+        AnnotationValue rewriteValue = ElementUtils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn");
+        List<TypeMirror> exceptionTypes = ElementUtils.getAnnotationValueList(TypeMirror.class, method.getMarkerAnnotation(), "rewriteOn");
+        List<SpecializationThrowsData> exceptionData = new ArrayList<>();
+        for (TypeMirror exceptionType : exceptionTypes) {
+            SpecializationThrowsData throwsData = new SpecializationThrowsData(method.getMarkerAnnotation(), rewriteValue, exceptionType);
+            if (!ElementUtils.canThrowType(method.getMethod().getThrownTypes(), exceptionType)) {
+                throwsData.addError("Method must specify a throws clause with the exception type '%s'.", ElementUtils.getQualifiedName(exceptionType));
+            }
+            exceptionData.add(throwsData);
+        }
+
+        Collections.sort(exceptionData, new Comparator<SpecializationThrowsData>() {
+
+            @Override
+            public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) {
+                return ElementUtils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass());
+            }
+        });
+        SpecializationData specialization = new SpecializationData(getNode(), method, SpecializationKind.SPECIALIZED, exceptionData);
+
+        String insertBeforeName = ElementUtils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "insertBefore");
+        if (!insertBeforeName.equals("")) {
+            specialization.setInsertBeforeName(insertBeforeName);
+        }
+
+        List<String> guardDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards");
+        List<GuardExpression> guardExpressions = new ArrayList<>();
+        for (String guardDef : guardDefs) {
+            guardExpressions.add(new GuardExpression(guardDef));
+        }
+        specialization.setGuards(guardExpressions);
+
+        List<String> containsDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "contains");
+        Set<String> containsNames = specialization.getContainsNames();
+        containsNames.clear();
+        if (containsDefs != null) {
+            for (String include : containsDefs) {
+                if (!containsNames.contains(include)) {
+                    specialization.getContainsNames().add(include);
+                } else {
+                    AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
+                    specialization.addError(value, "Duplicate contains declaration '%s'.", include);
+                }
+            }
+
+        }
+
+        List<String> assumptionDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "assumptions");
+        specialization.setAssumptions(assumptionDefs);
+
+        for (String assumption : assumptionDefs) {
+            if (!getNode().getAssumptions().contains(assumption)) {
+                specialization.addError("Undeclared assumption '%s' used. Use @NodeAssumptions to declare them.", assumption);
+            }
+        }
+
+        return specialization;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCastParser.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+class TypeCastParser extends TypeSystemMethodParser<TypeCastData> {
+
+    public TypeCastParser(ProcessorContext context, TypeSystemData typeSystem) {
+        super(context, typeSystem);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "as");
+        if (targetType == null) {
+            return null;
+        }
+        MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", targetType.getPrimitiveType()));
+        spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors()));
+        return spec;
+    }
+
+    @Override
+    public TypeCastData create(TemplateMethod method, boolean invalid) {
+        if (invalid) {
+            return new TypeCastData(method, null, null);
+        }
+
+        TypeData targetType = findTypeByMethodName(method, "as");
+        Parameter parameter = method.findParameter("valueValue");
+
+        TypeData sourceType = null;
+        if (parameter != null) {
+            sourceType = getTypeSystem().findTypeData(parameter.getType());
+        }
+        TypeCastData cast = new TypeCastData(method, sourceType, targetType);
+
+        if (targetType != method.getReturnType().getTypeSystemType()) {
+            cast.addError("Cast type %s does not match to the returned type %s.", ElementUtils.getSimpleName(targetType.getPrimitiveType()),
+                            method.getReturnType() != null ? ElementUtils.getSimpleName(method.getReturnType().getTypeSystemType().getPrimitiveType()) : null);
+        }
+        return cast;
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return TypeCast.class;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCheckParser.java	Mon Aug 11 15:57:14 2014 +0200
@@ -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.dsl.processor.parser;
+
+import java.lang.annotation.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+class TypeCheckParser extends TypeSystemMethodParser<TypeCheckData> {
+
+    public TypeCheckParser(ProcessorContext context, TypeSystemData typeSystem) {
+        super(context, typeSystem);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "is");
+        if (targetType == null) {
+            return null;
+        }
+        MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", getContext().getType(boolean.class)));
+        spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors()));
+        return spec;
+    }
+
+    @Override
+    public TypeCheckData create(TemplateMethod method, boolean invalid) {
+        TypeData checkedType = findTypeByMethodName(method, "is");
+        assert checkedType != null;
+        Parameter parameter = method.findParameter("valueValue");
+        assert parameter != null;
+        return new TypeCheckData(method, checkedType, parameter.getTypeSystemType());
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return TypeCheck.class;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemMethodParser.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+abstract class TypeSystemMethodParser<E extends TemplateMethod> extends TemplateMethodParser<TypeSystemData, E> {
+
+    public TypeSystemMethodParser(ProcessorContext context, TypeSystemData typeSystem) {
+        super(context, typeSystem);
+    }
+
+    @Override
+    public final boolean isParsable(ExecutableElement method) {
+        return ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
+    }
+
+    protected TypeData findTypeByMethodName(String methodName, String prefix) {
+        String typeName = methodName.substring(prefix.length(), methodName.length());
+        TypeData type = getTypeSystem().findType(typeName);
+        return type;
+    }
+
+    protected TypeData findTypeByMethodName(TemplateMethod method, String prefix) {
+        String methodName = method.getMethodName();
+        if (!methodName.startsWith(prefix)) {
+            String annotationName = ElementUtils.getSimpleName(method.getMessageAnnotation().getAnnotationType());
+            method.addError("Methods annotated with %s must match the pattern '%s'.", annotationName, String.format("%s${typeName}", prefix));
+            return null;
+        }
+        String typeName = methodName.substring(prefix.length(), methodName.length());
+        TypeData type = getTypeSystem().findType(typeName);
+        if (type == null) {
+            String annotationName = TypeSystem.class.getSimpleName();
+            method.addError("Type '%s' is not declared in this @%s.", typeName, annotationName);
+            return null;
+        }
+
+        return type;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java	Mon Aug 11 15:57:14 2014 +0200
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.generator.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class TypeSystemParser extends AbstractParser<TypeSystemData> {
+
+    public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(TypeSystem.class, ExpectError.class);
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return TypeSystem.class;
+    }
+
+    @Override
+    protected TypeSystemData parse(Element element, AnnotationMirror mirror) {
+        TypeElement templateType = (TypeElement) element;
+        AnnotationMirror templateTypeAnnotation = mirror;
+        TypeSystemData typeSystem = new TypeSystemData(context, templateType, templateTypeAnnotation);
+
+        // annotation type on class path!?
+        TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName());
+        if (annotationTypeElement == null) {
+            typeSystem.addError("Required class %s is not on the classpath.", getAnnotationType().getName());
+        }
+        if (templateType.getModifiers().contains(Modifier.PRIVATE)) {
+            typeSystem.addError("A @%s must have at least package protected visibility.", getAnnotationType().getName());
+        }
+
+        if (templateType.getModifiers().contains(Modifier.FINAL)) {
+            typeSystem.addError("The @%s must not be final.", getAnnotationType().getName());
+        }
+        if (typeSystem.hasErrors()) {
+            return typeSystem;
+        }
+
+        typeSystem.setTypes(parseTypes(typeSystem));
+        if (typeSystem.hasErrors()) {
+            return typeSystem;
+        }
+
+        TypeMirror genericType = context.getType(Object.class);
+        TypeData voidType = new TypeData(typeSystem, typeSystem.getTypes().size(), null, context.getType(void.class), context.getType(Void.class));
+
+        typeSystem.setGenericType(genericType);
+        typeSystem.setVoidType(voidType);
+
+        verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class);
+
+        List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType));
+        List<ImplicitCastData> implicitCasts = new ImplicitCastParser(context, typeSystem).parse(elements);
+        List<TypeCastData> casts = new TypeCastParser(context, typeSystem).parse(elements);
+        List<TypeCheckData> checks = new TypeCheckParser(context, typeSystem).parse(elements);
+
+        if (casts == null || checks == null || implicitCasts == null) {
+            return typeSystem;
+        }
+
+        typeSystem.setImplicitCasts(implicitCasts);
+        typeSystem.setCasts(casts);
+        typeSystem.setChecks(checks);
+
+        if (typeSystem.hasErrors()) {
+            return typeSystem;
+        }
+
+        for (TypeCheckData check : checks) {
+            check.getCheckedType().addTypeCheck(check);
+        }
+
+        for (TypeCastData cast : casts) {
+            cast.getTargetType().addTypeCast(cast);
+        }
+
+        verifyGenericTypeChecksAndCasts(typeSystem);
+        verifyMethodSignatures(typeSystem);
+        verifyNamesUnique(typeSystem);
+
+        return typeSystem;
+    }
+
+    private void verifyExclusiveMethodAnnotation(Template template, Class<?>... annotationTypes) {
+        List<ExecutableElement> methods = ElementFilter.methodsIn(template.getTemplateType().getEnclosedElements());
+        for (ExecutableElement method : methods) {
+            List<AnnotationMirror> foundAnnotations = new ArrayList<>();
+            for (int i = 0; i < annotationTypes.length; i++) {
+                Class<?> annotationType = annotationTypes[i];
+                AnnotationMirror mirror = ElementUtils.findAnnotationMirror(context.getEnvironment(), method, annotationType);
+                if (mirror != null) {
+                    foundAnnotations.add(mirror);
+                }
+            }
+            if (foundAnnotations.size() > 1) {
+                List<String> annotationNames = new ArrayList<>();
+                for (AnnotationMirror mirror : foundAnnotations) {
+                    annotationNames.add("@" + ElementUtils.getSimpleName(mirror.getAnnotationType()));
+                }
+
+                template.addError("Non exclusive usage of annotations %s.", annotationNames);
+            }
+        }
+    }
+
+    private static void verifyGenericTypeChecksAndCasts(TypeSystemData typeSystem) {
+        for (TypeData type : typeSystem.getTypes()) {
+            if (!type.getTypeChecks().isEmpty()) {
+                boolean hasGeneric = false;
+                for (TypeCheckData typeCheck : type.getTypeChecks()) {
+                    if (typeCheck.isGeneric()) {
+                        hasGeneric = true;
+                        break;
+                    }
+                }
+                if (!hasGeneric) {
+                    type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.",
+                                    TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type), ElementUtils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(),
+                                    Object.class.getSimpleName());
+                }
+            }
+            if (!type.getTypeCasts().isEmpty()) {
+                boolean hasGeneric = false;
+                for (TypeCastData typeCast : type.getTypeCasts()) {
+                    if (typeCast.isGeneric()) {
+                        hasGeneric = true;
+                        break;
+                    }
+                }
+                if (!hasGeneric) {
+                    type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.",
+                                    TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type), ElementUtils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(),
+                                    Object.class.getSimpleName());
+                }
+            }
+        }
+    }
+
+    private List<TypeData> parseTypes(TypeSystemData typeSystem) {
+        List<TypeData> types = new ArrayList<>();
+        List<TypeMirror> typeMirrors = ElementUtils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value");
+        if (typeMirrors.isEmpty()) {
+            typeSystem.addError("At least one type must be defined.");
+            return types;
+        }
+
+        final AnnotationValue annotationValue = ElementUtils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "value");
+        final TypeMirror objectType = context.getType(Object.class);
+
+        int index = 0;
+        for (TypeMirror primitiveType : typeMirrors) {
+            TypeMirror boxedType = ElementUtils.boxType(context, primitiveType);
+            TypeData typeData = new TypeData(typeSystem, index, annotationValue, primitiveType, boxedType);
+
+            if (isPrimitiveWrapper(primitiveType)) {
+                typeData.addError("Types must not contain primitive wrapper types.");
+            }
+
+            if (ElementUtils.typeEquals(boxedType, objectType)) {
+                typeData.addError("Types must not contain the generic type java.lang.Object.");
+            }
+
+            types.add(typeData);
+            index++;
+        }
+
+        verifyTypeOrder(types);
+
+        types.add(new TypeData(typeSystem, index, annotationValue, objectType, objectType));
+
+        return types;
+    }
+
+    private static void verifyTypeOrder(List<TypeData> types) {
+        Map<String, List<String>> invalidTypes = new HashMap<>();
+
+        for (int i = types.size() - 1; i >= 0; i--) {
+            TypeData typeData = types.get(i);
+            TypeMirror type = typeData.getBoxedType();
+            if (invalidTypes.containsKey(ElementUtils.getQualifiedName(type))) {
+                typeData.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(ElementUtils.getQualifiedName(type)), ElementUtils.getQualifiedName(type));
+            }
+            List<String> nextInvalidTypes = ElementUtils.getQualifiedSuperTypeNames(ElementUtils.fromTypeMirror(type));
+            nextInvalidTypes.add(getQualifiedName(type));
+
+            for (String qualifiedName : nextInvalidTypes) {
+                List<String> inheritedTypes = invalidTypes.get(qualifiedName);
+                if (inheritedTypes == null) {
+                    inheritedTypes = new ArrayList<>();
+                    invalidTypes.put(qualifiedName, inheritedTypes);
+                }
+                inheritedTypes.add(ElementUtils.getQualifiedName(typeData.getBoxedType()));
+            }
+        }
+    }
+
+    private boolean isPrimitiveWrapper(TypeMirror type) {
+        Types types = context.getEnvironment().getTypeUtils();
+        for (TypeKind kind : TypeKind.values()) {
+            if (!kind.isPrimitive()) {
+                continue;
+            }
+            if (ElementUtils.typeEquals(type, types.boxedClass(types.getPrimitiveType(kind)).asType())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void verifyMethodSignatures(TypeSystemData typeSystem) {
+        Set<String> generatedIsMethodNames = new HashSet<>();
+        Set<String> generatedAsMethodNames = new HashSet<>();
+        Set<String> generatedExpectMethodNames = new HashSet<>();
+
+        for (TypeData typeData : typeSystem.getTypes()) {
+            generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData));
+            generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData));
+            generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData));
+        }
+
+        List<ExecutableElement> methods = ElementFilter.methodsIn(typeSystem.getTemplateType().getEnclosedElements());
+        for (ExecutableElement method : methods) {
+            if (method.getModifiers().contains(Modifier.PRIVATE)) {
+                // will not conflict overridden methods
+                continue;
+            } else if (method.getParameters().size() != 1) {
+                continue;
+            }
+            String methodName = method.getSimpleName().toString();
+            if (generatedIsMethodNames.contains(methodName)) {
+                verifyIsMethod(typeSystem, method);
+            } else if (generatedAsMethodNames.contains(methodName)) {
+                verifyAsMethod(typeSystem, method);
+            } else if (generatedExpectMethodNames.contains(methodName)) {
+                verifyExpectMethod(typeSystem);
+            }
+        }
+    }
+
+    private boolean verifyIsMethod(TypeSystemData typeSystem, ExecutableElement method) {
+        AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, TypeCheck.class);
+        if (mirror == null) {
+            typeSystem.addError("Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName());
+            return false;
+        }
+        return true;
+    }
+
+    private boolean verifyAsMethod(TypeSystemData typeSystem, ExecutableElement method) {
+        AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, TypeCast.class);
+        if (mirror == null) {
+            typeSystem.addError("Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName());
+            return false;
+        }
+        return true;
+    }
+
+    private static boolean verifyExpectMethod(TypeSystemData typeSystem) {
+        typeSystem.addError("Method starting with the pattern expect${typeName} must not be declared manually.");
+        return false;
+    }
+
+    private static void verifyNamesUnique(TypeSystemData typeSystem) {
+        List<TypeData> types = typeSystem.getTypes();
+        for (int i = 0; i < types.size(); i++) {
+            for (int j = i + 1; j < types.size(); j++) {
+                String name1 = ElementUtils.getSimpleName(types.get(i).getBoxedType());
+                String name2 = ElementUtils.getSimpleName(types.get(j).getBoxedType());
+                if (name1.equalsIgnoreCase(name2)) {
+                    typeSystem.addError("Two types result in the same name: %s, %s.", name1, name2);
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public class ActualParameter {
-
-    private final ParameterSpec specification;
-    private TypeData typeSystemType;
-    private TemplateMethod method;
-    private final String localName;
-    private final int specificationVarArgsIndex;
-    private final int typeVarArgsIndex;
-    private final TypeMirror actualType;
-
-    public ActualParameter(ParameterSpec specification, TypeMirror actualType, int specificationVarArgsIndex, int typeVarArgsIndex) {
-        this.specification = specification;
-        this.actualType = actualType;
-        this.typeSystemType = null;
-
-        this.specificationVarArgsIndex = specificationVarArgsIndex;
-
-        String valueName = specification.getName() + "Value";
-        if (specificationVarArgsIndex > -1) {
-            valueName += specificationVarArgsIndex;
-        }
-        this.typeVarArgsIndex = typeVarArgsIndex;
-        this.localName = valueName;
-    }
-
-    public ActualParameter(ParameterSpec specification, TypeData actualType, int specificationIndex, int varArgsIndex) {
-        this(specification, actualType.getPrimitiveType(), specificationIndex, varArgsIndex);
-        this.typeSystemType = actualType;
-    }
-
-    public ActualParameter(ActualParameter parameter, TypeData otherType) {
-        this(parameter.specification, otherType, parameter.specificationVarArgsIndex, parameter.typeVarArgsIndex);
-    }
-
-    public ActualParameter(ActualParameter parameter) {
-        this.specification = parameter.specification;
-        this.actualType = parameter.actualType;
-        this.typeSystemType = parameter.typeSystemType;
-        this.specificationVarArgsIndex = parameter.specificationVarArgsIndex;
-        this.localName = parameter.localName;
-        this.typeVarArgsIndex = parameter.typeVarArgsIndex;
-    }
-
-    public int getTypeVarArgsIndex() {
-        return typeVarArgsIndex;
-    }
-
-    public int getSpecificationVarArgsIndex() {
-        return specificationVarArgsIndex;
-    }
-
-    public String getLocalName() {
-        return localName;
-    }
-
-    void setMethod(TemplateMethod method) {
-        this.method = method;
-    }
-
-    public ParameterSpec getSpecification() {
-        return specification;
-    }
-
-    public TemplateMethod getMethod() {
-        return method;
-    }
-
-    public TypeMirror getType() {
-        return actualType;
-    }
-
-    public TypeData getTypeSystemType() {
-        return typeSystemType;
-    }
-
-    public boolean isTypeVarArgs() {
-        return typeVarArgsIndex >= 0;
-    }
-
-    public ActualParameter getPreviousParameter() {
-        return method.getPreviousParam(this);
-    }
-
-    @Override
-    public String toString() {
-        return Utils.getSimpleName(actualType);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ClassElementFactory.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import static com.oracle.truffle.dsl.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.api.dsl.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-
-public abstract class ClassElementFactory<M> extends CodeElementFactory<M> {
-
-    @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();
-        TypeElement superClass = fromTypeMirror(clazz.getSuperclass());
-        ExecutableElement constructor = findConstructor(superClass);
-        if (constructor != null && constructor.getParameters().size() > 0) {
-            builder.startStatement();
-            builder.startSuperCall();
-            for (VariableElement parameter : constructor.getParameters()) {
-                method.addParameter(new CodeVariableElement(parameter.asType(), parameter.getSimpleName().toString()));
-                builder.string(parameter.getSimpleName().toString());
-            }
-            builder.end(); // super
-            builder.end(); // statement
-        }
-
-        for (VariableElement field : clazz.getFields()) {
-            if (field.getModifiers().contains(STATIC)) {
-                continue;
-            }
-            String fieldName = field.getSimpleName().toString();
-            method.addParameter(new CodeVariableElement(field.asType(), fieldName));
-            builder.startStatement();
-            builder.string("this.");
-            builder.string(fieldName);
-            builder.string(" = ");
-            if (isAssignable(field.asType(), getContext().getTruffleTypes().getNode())) {
-                builder.string("adoptChild(").string(fieldName).string(")");
-            } else {
-                builder.string(fieldName);
-            }
-            builder.end(); // statement
-        }
-
-        return method;
-    }
-
-    private static ExecutableElement findConstructor(TypeElement clazz) {
-        List<ExecutableElement> constructors = ElementFilter.constructorsIn(clazz.getEnclosedElements());
-        if (constructors.isEmpty()) {
-            return null;
-        } else {
-            return constructors.get(0);
-        }
-    }
-
-    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();
-
-        PackageElement pack = getContext().getEnvironment().getElementUtils().getPackageOf(templateType);
-        CodeTypeElement clazz = new CodeTypeElement(modifiers, enumType ? ElementKind.ENUM : ElementKind.CLASS, pack, simpleName);
-        TypeMirror resolvedSuperType = superType;
-        if (resolvedSuperType == null) {
-            resolvedSuperType = getContext().getType(Object.class);
-        }
-        clazz.setSuperClass(resolvedSuperType);
-
-        CodeAnnotationMirror generatedByAnnotation = new CodeAnnotationMirror((DeclaredType) getContext().getType(GeneratedBy.class));
-        generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("value"), new CodeAnnotationValue(templateType.asType()));
-        if (model.getTemplateMethodName() != null) {
-            generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("methodName"), new CodeAnnotationValue(model.getTemplateMethodName()));
-        }
-
-        clazz.addAnnotationMirror(generatedByAnnotation);
-
-        context.registerType(model.getTemplateType(), clazz.asType());
-
-        return clazz;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CodeElementFactory.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-
-public abstract class CodeElementFactory<M> {
-
-    protected final ProcessorContext context;
-    private M model;
-
-    private CodeElement<? super Element> element;
-
-    public CodeElementFactory() {
-        this.context = ProcessorContext.getInstance();
-    }
-
-    protected abstract CodeElement<?> create(M m);
-
-    @SuppressWarnings("unused")
-    protected void createChildren(M m) {
-    }
-
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    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);
-        }
-        return element;
-    }
-
-    @SuppressWarnings("rawtypes")
-    public CodeElement getElement() {
-        return element;
-    }
-
-    protected <MO, K extends Element> void add(CodeElementFactory<MO> factory, MO m) {
-        factory.process(this.element, m);
-    }
-
-    public ProcessorContext getContext() {
-        return context;
-    }
-
-    public M getModel() {
-        return model;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CompilationUnitFactory.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import com.oracle.truffle.dsl.processor.ast.*;
-
-public abstract class CompilationUnitFactory<M> extends CodeElementFactory<M> {
-
-    @Override
-    public final CodeCompilationUnit create(M m) {
-        return new CodeCompilationUnit();
-    }
-
-    @SuppressWarnings("rawtypes")
-    @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.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,260 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.tools.Diagnostic.Kind;
-
-import com.oracle.truffle.dsl.processor.*;
-
-public abstract class MessageContainer implements Iterable<MessageContainer> {
-
-    private final List<Message> messages = new ArrayList<>();
-
-    public final void addWarning(String text, Object... params) {
-        getMessages().add(new Message(null, this, String.format(text, params), Kind.WARNING));
-    }
-
-    public final void addWarning(AnnotationValue value, String text, Object... params) {
-        getMessages().add(new Message(value, this, String.format(text, params), Kind.WARNING));
-    }
-
-    public final void addError(String text, Object... params) {
-        addError(null, text, params);
-    }
-
-    public final void addError(AnnotationValue value, String text, Object... params) {
-        getMessages().add(new Message(value, this, String.format(text, params), Kind.ERROR));
-    }
-
-    protected List<MessageContainer> findChildContainers() {
-        return Collections.emptyList();
-    }
-
-    public abstract Element getMessageElement();
-
-    public MessageContainer getBaseContainer() {
-        return null;
-    }
-
-    public Iterator<MessageContainer> iterator() {
-        return findChildContainers().iterator();
-    }
-
-    public final void emitMessages(ProcessorContext context, Log log) {
-        emitMessagesImpl(context, log, new HashSet<MessageContainer>(), null);
-    }
-
-    private void emitMessagesImpl(ProcessorContext context, Log log, Set<MessageContainer> visitedSinks, List<Message> verifiedMessages) {
-        List<Message> childMessages;
-        if (verifiedMessages == null) {
-            childMessages = collectMessagesWithElementChildren(new HashSet<MessageContainer>(), getMessageElement());
-        } else {
-            childMessages = verifiedMessages;
-        }
-        verifyExpectedMessages(context, log, childMessages);
-
-        for (int i = getMessages().size() - 1; i >= 0; i--) {
-            emitDefault(context, log, getMessages().get(i));
-        }
-
-        for (MessageContainer sink : findChildContainers()) {
-            if (visitedSinks.contains(sink)) {
-                continue;
-            }
-
-            visitedSinks.add(sink);
-            if (sink.getMessageElement() == this.getMessageElement()) {
-                sink.emitMessagesImpl(context, log, visitedSinks, childMessages);
-            } else {
-                sink.emitMessagesImpl(context, log, visitedSinks, null);
-            }
-        }
-    }
-
-    private List<Message> collectMessagesWithElementChildren(Set<MessageContainer> visitedSinks, Element e) {
-        if (visitedSinks.contains(this)) {
-            return Collections.emptyList();
-        }
-        visitedSinks.add(this);
-
-        List<Message> foundMessages = new ArrayList<>();
-        if (Utils.typeEquals(getMessageElement().asType(), e.asType())) {
-            foundMessages.addAll(getMessages());
-        }
-        for (MessageContainer sink : findChildContainers()) {
-            foundMessages.addAll(sink.collectMessagesWithElementChildren(visitedSinks, e));
-        }
-        return foundMessages;
-    }
-
-    private void verifyExpectedMessages(ProcessorContext context, Log log, List<Message> msgs) {
-        TypeElement expectError = context.getTruffleTypes().getExpectError();
-        if (expectError != null) {
-            Element element = getMessageElement();
-            AnnotationMirror mirror = Utils.findAnnotationMirror(element.getAnnotationMirrors(), expectError);
-            if (mirror != null) {
-                List<String> values = Utils.getAnnotationValueList(String.class, mirror, "value");
-                if (values == null) {
-                    values = Collections.emptyList();
-                }
-                if (values.size() != msgs.size()) {
-                    log.message(Kind.ERROR, element, mirror, Utils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size()));
-                }
-            }
-        }
-    }
-
-    private void emitDefault(ProcessorContext context, Log log, Message message) {
-        Kind kind = message.getKind();
-
-        Element messageElement = getMessageElement();
-        AnnotationMirror messageAnnotation = getMessageAnnotation();
-        AnnotationValue messageValue = getMessageAnnotationValue();
-        if (message.getAnnotationValue() != null) {
-            messageValue = message.getAnnotationValue();
-        }
-
-        String text = message.getText();
-
-        TypeElement expectError = context.getTruffleTypes().getExpectError();
-        if (expectError != null) {
-            AnnotationMirror mirror = Utils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError);
-            if (mirror != null) {
-                List<String> expectedTexts = Utils.getAnnotationValueList(String.class, mirror, "value");
-                boolean found = false;
-                for (String expectedText : expectedTexts) {
-                    if (expectedText.endsWith("%") && text.startsWith(expectedText.substring(0, expectedText.length() - 1))) {
-                        found = true;
-                        break;
-                    } else if (text.equals(expectedText)) {
-                        found = true;
-                        break;
-                    }
-                }
-                if (!found) {
-                    log.message(kind, messageElement, mirror, Utils.getAnnotationValue(mirror, "value"), "Message expected one of '%s' but was '%s'.", expectedTexts, text);
-                } else {
-                    return;
-                }
-
-            }
-        }
-
-        log.message(kind, messageElement, messageAnnotation, messageValue, text);
-    }
-
-    public AnnotationMirror getMessageAnnotation() {
-        return null;
-    }
-
-    public AnnotationValue getMessageAnnotationValue() {
-        return null;
-    }
-
-    public final boolean hasErrors() {
-        return hasErrorsImpl(new HashSet<MessageContainer>());
-    }
-
-    public final List<Message> collectMessages() {
-        List<Message> collectedMessages = new ArrayList<>();
-        collectMessagesImpl(collectedMessages, new HashSet<MessageContainer>());
-        return collectedMessages;
-    }
-
-    private void collectMessagesImpl(List<Message> collectedMessages, Set<MessageContainer> visitedSinks) {
-        collectedMessages.addAll(getMessages());
-        for (MessageContainer sink : findChildContainers()) {
-            if (visitedSinks.contains(sink)) {
-                return;
-            }
-
-            visitedSinks.add(sink);
-            sink.collectMessagesImpl(collectedMessages, visitedSinks);
-        }
-    }
-
-    private boolean hasErrorsImpl(Set<MessageContainer> visitedSinks) {
-        for (Message msg : getMessages()) {
-            if (msg.getKind() == Kind.ERROR) {
-                return true;
-            }
-        }
-        for (MessageContainer sink : findChildContainers()) {
-            if (visitedSinks.contains(sink)) {
-                return false;
-            }
-
-            visitedSinks.add(sink);
-
-            if (sink.hasErrorsImpl(visitedSinks)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public List<Message> getMessages() {
-        return messages;
-    }
-
-    public static final class Message {
-
-        private final MessageContainer originalContainer;
-        private final AnnotationValue annotationValue;
-        private final String text;
-        private final Kind kind;
-
-        public Message(AnnotationValue annotationValue, MessageContainer originalContainer, String text, Kind kind) {
-            this.annotationValue = annotationValue;
-            this.originalContainer = originalContainer;
-            this.text = text;
-            this.kind = kind;
-        }
-
-        public AnnotationValue getAnnotationValue() {
-            return annotationValue;
-        }
-
-        public MessageContainer getOriginalContainer() {
-            return originalContainer;
-        }
-
-        public String getText() {
-            return text;
-        }
-
-        public Kind getKind() {
-            return kind;
-        }
-
-        @Override
-        public String toString() {
-            return kind + ": " + text;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,239 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import java.util.*;
-
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-
-public class MethodSpec {
-
-    private final ParameterSpec returnType;
-    private final List<ParameterSpec> optional = new ArrayList<>();
-    private final List<ParameterSpec> required = new ArrayList<>();
-
-    private boolean ignoreAdditionalParameters;
-    private boolean ignoreAdditionalSpecifications;
-    private boolean variableRequiredParameters;
-
-    private List<TypeDef> typeDefinitions;
-
-    public MethodSpec(ParameterSpec returnType) {
-        this.returnType = returnType;
-    }
-
-    public void setVariableRequiredParameters(boolean variableRequiredParameters) {
-        this.variableRequiredParameters = variableRequiredParameters;
-    }
-
-    public boolean isVariableRequiredParameters() {
-        return variableRequiredParameters;
-    }
-
-    public void setIgnoreAdditionalParameters(boolean ignoreAdditionalParameter) {
-        this.ignoreAdditionalParameters = ignoreAdditionalParameter;
-    }
-
-    public boolean isIgnoreAdditionalParameters() {
-        return ignoreAdditionalParameters;
-    }
-
-    public void addOptional(ParameterSpec spec) {
-        optional.add(spec);
-    }
-
-    public ParameterSpec addRequired(ParameterSpec spec) {
-        required.add(spec);
-        return spec;
-    }
-
-    public ParameterSpec getReturnType() {
-        return returnType;
-    }
-
-    public List<ParameterSpec> getRequired() {
-        return required;
-    }
-
-    public List<ParameterSpec> getOptional() {
-        return optional;
-    }
-
-    public List<ParameterSpec> getAll() {
-        List<ParameterSpec> specs = new ArrayList<>();
-        specs.add(getReturnType());
-        specs.addAll(getOptional());
-        specs.addAll(getRequired());
-        return specs;
-    }
-
-    public ParameterSpec findParameterSpec(String name) {
-        for (ParameterSpec spec : getAll()) {
-            if (spec.getName().equals(name)) {
-                return spec;
-            }
-        }
-        return null;
-    }
-
-    public void applyTypeDefinitions(String prefix) {
-        this.typeDefinitions = createTypeDefinitions(prefix);
-    }
-
-    private List<TypeDef> createTypeDefinitions(String prefix) {
-        List<TypeDef> typeDefs = new ArrayList<>();
-
-        int defIndex = 0;
-        for (ParameterSpec spec : getAll()) {
-            List<TypeMirror> allowedTypes = spec.getAllowedTypes();
-            List<TypeMirror> types = spec.getAllowedTypes();
-            if (types != null && allowedTypes.size() > 1) {
-                TypeDef foundDef = null;
-                for (TypeDef def : typeDefs) {
-                    if (allowedTypes.equals(def.getTypes())) {
-                        foundDef = def;
-                        break;
-                    }
-                }
-                if (foundDef == null) {
-                    foundDef = new TypeDef(types, prefix + defIndex);
-                    typeDefs.add(foundDef);
-                    defIndex++;
-                }
-
-                spec.setTypeDefinition(foundDef);
-            }
-        }
-
-        return typeDefs;
-    }
-
-    public String toSignatureString(String methodName) {
-        StringBuilder b = new StringBuilder();
-        b.append("    ");
-        b.append(createTypeSignature(returnType, true));
-
-        b.append(" ");
-        b.append(methodName);
-        b.append("(");
-
-        String sep = "";
-
-        for (ParameterSpec optionalSpec : getOptional()) {
-            b.append(sep);
-            b.append("[");
-            b.append(createTypeSignature(optionalSpec, false));
-            b.append("]");
-            sep = ", ";
-        }
-
-        for (int i = 0; i < getRequired().size(); i++) {
-            ParameterSpec requiredSpec = getRequired().get(i);
-            b.append(sep);
-
-            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
-                b.append(("{"));
-            }
-            b.append(createTypeSignature(requiredSpec, false));
-            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
-                b.append(("}"));
-            }
-
-            sep = ", ";
-        }
-
-        b.append(")");
-
-        if (typeDefinitions != null && !typeDefinitions.isEmpty()) {
-            b.append("\n\n");
-
-            String lineSep = "";
-            for (TypeDef def : typeDefinitions) {
-                b.append(lineSep);
-                b.append("    <").append(def.getName()).append(">");
-                b.append(" = {");
-                String separator = "";
-                for (TypeMirror type : def.getTypes()) {
-                    b.append(separator).append(Utils.getSimpleName(type));
-                    separator = ", ";
-                }
-                b.append("}");
-                lineSep = "\n";
-
-            }
-        }
-        return b.toString();
-    }
-
-    private static String createTypeSignature(ParameterSpec spec, boolean typeOnly) {
-        StringBuilder builder = new StringBuilder();
-        TypeDef foundTypeDef = spec.getTypeDefinition();
-        if (foundTypeDef != null) {
-            builder.append("<" + foundTypeDef.getName() + ">");
-        } else if (spec.getAllowedTypes().size() >= 1) {
-            builder.append(Utils.getSimpleName(spec.getAllowedTypes().get(0)));
-        } else {
-            builder.append("void");
-        }
-        if (!typeOnly) {
-            builder.append(" ");
-            builder.append(spec.getName());
-        }
-        return builder.toString();
-    }
-
-    @Override
-    public String toString() {
-        return toSignatureString("methodName");
-    }
-
-    static class TypeDef {
-
-        private final List<TypeMirror> types;
-        private final String name;
-
-        public TypeDef(List<TypeMirror> types, String name) {
-            this.types = types;
-            this.name = name;
-        }
-
-        public List<TypeMirror> getTypes() {
-            return types;
-        }
-
-        public String getName() {
-            return name;
-        }
-    }
-
-    public void setIgnoreAdditionalSpecifications(boolean ignoreAdditoinalSpecifications) {
-        this.ignoreAdditionalSpecifications = ignoreAdditoinalSpecifications;
-    }
-
-    public boolean isIgnoreAdditionalSpecifications() {
-        return ignoreAdditionalSpecifications;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import java.util.*;
-
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.*;
-import com.oracle.truffle.dsl.processor.template.MethodSpec.TypeDef;
-
-public class ParameterSpec {
-
-    private final String name;
-    private final List<TypeMirror> allowedTypes;
-
-    /** Type is bound to local final variable. */
-    private boolean local;
-    private boolean signature;
-
-    /** Optional bound execution of node. */
-    private NodeExecutionData execution;
-    private TypeDef typeDefinition;
-
-    public ParameterSpec(String name, List<TypeMirror> allowedTypes) {
-        this.name = name;
-        this.allowedTypes = allowedTypes;
-    }
-
-    public ParameterSpec(String name, TypeMirror type) {
-        this(name, Arrays.asList(type));
-    }
-
-    public ParameterSpec(ParameterSpec o, List<TypeMirror> allowedTypes) {
-        this.name = o.name;
-        this.local = o.local;
-        this.typeDefinition = o.typeDefinition;
-        this.execution = o.execution;
-        this.signature = o.signature;
-        this.allowedTypes = allowedTypes;
-    }
-
-    public NodeExecutionData getExecution() {
-        return execution;
-    }
-
-    public void setExecution(NodeExecutionData executionData) {
-        this.execution = executionData;
-        this.signature = execution != null;
-    }
-
-    public void setSignature(boolean signature) {
-        this.signature = signature;
-    }
-
-    void setTypeDefinition(TypeDef typeDefinition) {
-        this.typeDefinition = typeDefinition;
-    }
-
-    TypeDef getTypeDefinition() {
-        return typeDefinition;
-    }
-
-    public void setLocal(boolean local) {
-        this.local = local;
-    }
-
-    public boolean isSignature() {
-        return signature;
-    }
-
-    public boolean isLocal() {
-        return local;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public List<TypeMirror> getAllowedTypes() {
-        return allowedTypes;
-    }
-
-    public boolean matches(TypeMirror actualType) {
-        for (TypeMirror mirror : allowedTypes) {
-            if (Utils.typeEquals(actualType, mirror)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return toSignatureString(false);
-    }
-
-    public String toSignatureString(boolean typeOnly) {
-        StringBuilder builder = new StringBuilder();
-        if (typeDefinition != null) {
-            builder.append("<" + typeDefinition.getName() + ">");
-        } else if (getAllowedTypes().size() >= 1) {
-            builder.append(Utils.getSimpleName(getAllowedTypes().get(0)));
-        } else {
-            builder.append("void");
-        }
-        if (!typeOnly) {
-            builder.append(" ");
-            builder.append(getName());
-        }
-        return builder.toString();
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/Template.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public abstract class Template extends MessageContainer {
-
-    private final ProcessorContext context;
-    private final TypeElement templateType;
-    private final String templateMethodName;
-    private final AnnotationMirror annotation;
-
-    public Template(ProcessorContext context, TypeElement templateType, String templateMethodName, AnnotationMirror annotation) {
-        this.context = context;
-        this.templateType = templateType;
-        this.templateMethodName = templateMethodName;
-        this.annotation = annotation;
-    }
-
-    public ProcessorContext getContext() {
-        return context;
-    }
-
-    @Override
-    public MessageContainer getBaseContainer() {
-        return this;
-    }
-
-    public abstract TypeSystemData getTypeSystem();
-
-    @Override
-    public Element getMessageElement() {
-        return templateType;
-    }
-
-    @Override
-    protected List<MessageContainer> findChildContainers() {
-        return Collections.emptyList();
-    }
-
-    public String getTemplateMethodName() {
-        return templateMethodName;
-    }
-
-    public TypeElement getTemplateType() {
-        return templateType;
-    }
-
-    public AnnotationMirror getTemplateTypeAnnotation() {
-        return annotation;
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + "[" + Utils.getSimpleName(getTemplateType()) + "]";
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,493 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-import com.oracle.truffle.dsl.processor.util.*;
-
-/**
- * Note: this class has a natural ordering that is inconsistent with equals.
- */
-public class TemplateMethod extends MessageContainer implements Comparable<TemplateMethod> {
-
-    public static final int NO_NATURAL_ORDER = -1;
-
-    private String id;
-    private final Template template;
-    private final int naturalOrder;
-    private final MethodSpec specification;
-    private final ExecutableElement method;
-    private final AnnotationMirror markerAnnotation;
-    private ActualParameter returnType;
-    private List<ActualParameter> parameters;
-
-    public TemplateMethod(String id, int naturalOrder, Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType,
-                    List<ActualParameter> parameters) {
-        this.template = template;
-        this.specification = specification;
-        this.naturalOrder = naturalOrder;
-        this.method = method;
-        this.markerAnnotation = markerAnnotation;
-        this.returnType = returnType;
-        this.parameters = new ArrayList<>();
-        for (ActualParameter param : parameters) {
-            ActualParameter newParam = new ActualParameter(param);
-            this.parameters.add(newParam);
-            newParam.setMethod(this);
-        }
-        this.id = id;
-    }
-
-    public int getNaturalOrder() {
-        return naturalOrder;
-    }
-
-    public TemplateMethod(TemplateMethod method) {
-        this(method.id, method.naturalOrder, method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters);
-        getMessages().addAll(method.getMessages());
-    }
-
-    public TemplateMethod(TemplateMethod method, ExecutableElement executable) {
-        this(method.id, method.naturalOrder, method.template, method.specification, executable, method.markerAnnotation, method.returnType, method.parameters);
-        getMessages().addAll(method.getMessages());
-    }
-
-    public void setParameters(List<ActualParameter> parameters) {
-        this.parameters = parameters;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return method;
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return markerAnnotation;
-    }
-
-    @Override
-    protected List<MessageContainer> findChildContainers() {
-        return Collections.emptyList();
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public Template getTemplate() {
-        return template;
-    }
-
-    public MethodSpec getSpecification() {
-        return specification;
-    }
-
-    public ActualParameter getReturnType() {
-        return returnType;
-    }
-
-    public void replaceParameter(String localName, ActualParameter newParameter) {
-        if (returnType.getLocalName().equals(localName)) {
-            returnType = newParameter;
-            returnType.setMethod(this);
-        }
-
-        for (ListIterator<ActualParameter> iterator = parameters.listIterator(); iterator.hasNext();) {
-            ActualParameter parameter = iterator.next();
-            if (parameter.getLocalName().equals(localName)) {
-                iterator.set(newParameter);
-                newParameter.setMethod(this);
-            }
-        }
-    }
-
-    public List<ActualParameter> getRequiredParameters() {
-        List<ActualParameter> requiredParameters = new ArrayList<>();
-        for (ActualParameter parameter : getParameters()) {
-            if (getSpecification().getRequired().contains(parameter.getSpecification())) {
-                requiredParameters.add(parameter);
-            }
-        }
-        return requiredParameters;
-    }
-
-    public Iterable<ActualParameter> getSignatureParameters() {
-        return new FilteredIterable<>(getParameters(), new Predicate<ActualParameter>() {
-            public boolean evaluate(ActualParameter value) {
-                return value.getSpecification().isSignature();
-            }
-        });
-    }
-
-    public List<ActualParameter> getParameters() {
-        return parameters;
-    }
-
-    public List<ActualParameter> findParameters(ParameterSpec spec) {
-        List<ActualParameter> foundParameters = new ArrayList<>();
-        for (ActualParameter param : getReturnTypeAndParameters()) {
-            if (param.getSpecification().getName().equals(spec.getName())) {
-                foundParameters.add(param);
-            }
-        }
-        return foundParameters;
-    }
-
-    public ActualParameter findParameter(String valueName) {
-        for (ActualParameter param : getReturnTypeAndParameters()) {
-            if (param.getLocalName().equals(valueName)) {
-                return param;
-            }
-        }
-        return null;
-    }
-
-    public List<ActualParameter> getReturnTypeAndParameters() {
-        List<ActualParameter> allParameters = new ArrayList<>(getParameters().size() + 1);
-        if (getReturnType() != null) {
-            allParameters.add(getReturnType());
-        }
-        allParameters.addAll(getParameters());
-        return Collections.unmodifiableList(allParameters);
-    }
-
-    public boolean canBeAccessedByInstanceOf(TypeMirror type) {
-        TypeMirror methodType = Utils.findNearestEnclosingType(getMethod()).asType();
-        return Utils.isAssignable(type, methodType) || Utils.isAssignable(methodType, type);
-    }
-
-    public ExecutableElement getMethod() {
-        return method;
-    }
-
-    public String getMethodName() {
-        if (getMethod() != null) {
-            return getMethod().getSimpleName().toString();
-        } else {
-            return "$synthetic";
-        }
-    }
-
-    public AnnotationMirror getMarkerAnnotation() {
-        return markerAnnotation;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s [id = %s, method = %s]", getClass().getSimpleName(), getId(), getMethod());
-    }
-
-    public ActualParameter getPreviousParam(ActualParameter searchParam) {
-        ActualParameter prev = null;
-        for (ActualParameter param : getParameters()) {
-            if (param == searchParam) {
-                return prev;
-            }
-            prev = param;
-        }
-        return prev;
-    }
-
-    @SuppressWarnings("unused")
-    public int getSignatureSize() {
-        int signatureSize = 0;
-        for (ActualParameter parameter : getSignatureParameters()) {
-            signatureSize++;
-        }
-        return signatureSize;
-    }
-
-    public TypeSignature getTypeSignature() {
-        TypeSignature signature = new TypeSignature();
-        signature.types.add(getReturnType().getTypeSystemType());
-        for (ActualParameter parameter : getSignatureParameters()) {
-            TypeData typeData = parameter.getTypeSystemType();
-            if (typeData != null) {
-                signature.types.add(typeData);
-            }
-        }
-        return signature;
-    }
-
-    public ActualParameter getSignatureParameter(int searchIndex) {
-        int index = 0;
-        for (ActualParameter parameter : getParameters()) {
-            if (!parameter.getSpecification().isSignature()) {
-                continue;
-            }
-            if (index == searchIndex) {
-                return parameter;
-            }
-            index++;
-        }
-        return null;
-    }
-
-    public void updateSignature(TypeSignature signature) {
-        // TODO(CH): fails in normal usage - output ok though
-        // assert signature.size() >= 1;
-
-        int signatureIndex = 0;
-        for (ActualParameter parameter : getReturnTypeAndParameters()) {
-            if (!parameter.getSpecification().isSignature()) {
-                continue;
-            }
-            if (signatureIndex >= signature.size()) {
-                break;
-            }
-            TypeData newType = signature.get(signatureIndex++);
-            if (!parameter.getTypeSystemType().equals(newType)) {
-                replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, newType));
-            }
-        }
-    }
-
-    @Override
-    public int compareTo(TemplateMethod o) {
-        if (this == o) {
-            return 0;
-        }
-
-        int compare = compareBySignature(o);
-        if (compare == 0) {
-            // if signature sorting failed sort by id
-            compare = getId().compareTo(o.getId());
-        }
-        if (compare == 0) {
-            // if still no difference sort by enclosing type name
-            TypeElement enclosingType1 = Utils.findNearestEnclosingType(getMethod());
-            TypeElement enclosingType2 = Utils.findNearestEnclosingType(o.getMethod());
-            compare = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString());
-        }
-        return compare;
-    }
-
-    public List<ActualParameter> getParametersAfter(ActualParameter genericParameter) {
-        boolean found = false;
-        List<ActualParameter> foundParameters = new ArrayList<>();
-        for (ActualParameter param : getParameters()) {
-            if (param.getLocalName().equals(genericParameter.getLocalName())) {
-                found = true;
-            } else if (found) {
-                foundParameters.add(param);
-            }
-        }
-        return foundParameters;
-    }
-
-    public int compareBySignature(TemplateMethod compareMethod) {
-        final TypeSystemData typeSystem = getTemplate().getTypeSystem();
-        if (typeSystem != compareMethod.getTemplate().getTypeSystem()) {
-            throw new IllegalStateException("Cannot compare two methods with different type systems.");
-        }
-
-        List<TypeMirror> signature1 = getSignatureTypes(this);
-        List<TypeMirror> signature2 = getSignatureTypes(compareMethod);
-
-        int result = 0;
-        for (int i = 0; i < Math.max(signature1.size(), signature2.size()); i++) {
-            TypeMirror t1 = i < signature1.size() ? signature1.get(i) : null;
-            TypeMirror t2 = i < signature2.size() ? signature2.get(i) : null;
-            result = compareParameter(typeSystem, t1, t2);
-            if (result != 0) {
-                break;
-            }
-        }
-
-        return result;
-    }
-
-    protected static int compareParameter(TypeSystemData data, TypeMirror signature1, TypeMirror signature2) {
-        if (signature1 == null) {
-            return 1;
-        } else if (signature2 == null) {
-            return -1;
-        }
-
-        if (Utils.typeEquals(signature1, signature2)) {
-            return 0;
-        }
-
-        int index1 = data.findType(signature1);
-        int index2 = data.findType(signature2);
-        if (index1 != -1 && index2 != -1) {
-            return index1 - index2;
-        }
-
-        // TODO this version if subclass of should be improved.
-        if (signature1.getKind() == TypeKind.DECLARED && signature2.getKind() == TypeKind.DECLARED) {
-            TypeElement element1 = Utils.fromTypeMirror(signature1);
-            TypeElement element2 = Utils.fromTypeMirror(signature2);
-
-            if (Utils.getDirectSuperTypes(element1).contains(element2)) {
-                return -1;
-            } else if (Utils.getDirectSuperTypes(element2).contains(element1)) {
-                return 1;
-            }
-        }
-        return Utils.getSimpleName(signature1).compareTo(Utils.getSimpleName(signature2));
-    }
-
-    public static List<TypeMirror> getSignatureTypes(TemplateMethod method) {
-        List<TypeMirror> types = new ArrayList<>();
-        for (ActualParameter param : method.getSignatureParameters()) {
-            types.add(param.getType());
-        }
-        return types;
-    }
-
-    public static class TypeSignature implements Iterable<TypeData>, Comparable<TypeSignature> {
-
-        final List<TypeData> types;
-
-        public TypeSignature() {
-            this.types = new ArrayList<>();
-        }
-
-        public TypeSignature(List<TypeData> signature) {
-            this.types = signature;
-        }
-
-        @Override
-        public int hashCode() {
-            return types.hashCode();
-        }
-
-        public int size() {
-            return types.size();
-        }
-
-        public TypeData get(int index) {
-            return types.get(index);
-        }
-
-        public int compareTo(TypeSignature other) {
-            if (this == other) {
-                return 0;
-            } else if (types.size() != other.types.size()) {
-                return types.size() - other.types.size();
-            } else if (types.isEmpty()) {
-                return 0;
-            }
-
-            for (int i = 0; i < types.size(); i++) {
-                TypeData type1 = types.get(i);
-                TypeData type2 = other.types.get(i);
-
-                int comparison = type1.compareTo(type2);
-                if (comparison != 0) {
-                    return comparison;
-                }
-            }
-
-            return 0;
-        }
-
-        public TypeSignature combine(TypeSignature genericSignature, TypeSignature other) {
-            assert types.size() == other.types.size();
-            assert genericSignature.types.size() == other.types.size();
-
-            if (this.equals(other)) {
-                return this;
-            }
-
-            TypeSignature signature = new TypeSignature();
-            for (int i = 0; i < types.size(); i++) {
-                TypeData type1 = types.get(i);
-                TypeData type2 = other.types.get(i);
-                if (type1.equals(type2)) {
-                    signature.types.add(type1);
-                } else {
-                    signature.types.add(genericSignature.types.get(i));
-                }
-            }
-            return signature;
-        }
-
-        public boolean equalsParameters(TypeSignature other) {
-            if (size() != other.size()) {
-                return false;
-            }
-            return types.subList(1, types.size()).equals(other.types.subList(1, other.types.size()));
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof TypeSignature) {
-                return ((TypeSignature) obj).types.equals(types);
-            }
-            return super.equals(obj);
-        }
-
-        public Iterator<TypeData> iterator() {
-            return types.iterator();
-        }
-
-        @Override
-        public String toString() {
-            return types.toString();
-        }
-
-        public boolean hasAnyParameterMatch(TypeSignature other) {
-            for (int i = 1; i < types.size(); i++) {
-                TypeData type1 = types.get(i);
-                TypeData type2 = other.types.get(i);
-                if (type1.equals(type2)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        public boolean isCompatibleTo(TypeSignature signature) {
-            if (size() != signature.size()) {
-                return false;
-            }
-
-            for (int i = 0; i < size(); i++) {
-                TypeData o1 = get(i);
-                TypeData o2 = signature.get(i);
-                if (o1.equals(o2)) {
-                    continue;
-                } else if (o2.isGeneric()) {
-                    continue;
-                } else {
-                    return false;
-                }
-            }
-            return true;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,357 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.template;
-
-import static com.oracle.truffle.dsl.processor.Utils.*;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.typesystem.*;
-
-public abstract class TemplateMethodParser<T extends Template, E extends TemplateMethod> {
-
-    private final ProcessorContext context;
-
-    protected final T template;
-
-    private boolean emitErrors = true;
-    private boolean parseNullOnError = false;
-    private boolean useVarArgs = false;
-
-    public TemplateMethodParser(ProcessorContext context, T template) {
-        this.template = template;
-        this.context = context;
-    }
-
-    protected void setUseVarArgs(boolean useVarArgs) {
-        this.useVarArgs = useVarArgs;
-    }
-
-    public boolean isUseVarArgs() {
-        return useVarArgs;
-    }
-
-    public boolean isEmitErrors() {
-        return emitErrors;
-    }
-
-    public void setParseNullOnError(boolean nullOnError) {
-        this.parseNullOnError = nullOnError;
-    }
-
-    public boolean isParseNullOnError() {
-        return parseNullOnError;
-    }
-
-    public void setEmitErrors(boolean emitErrors) {
-        this.emitErrors = emitErrors;
-    }
-
-    public ProcessorContext getContext() {
-        return context;
-    }
-
-    public TypeSystemData getTypeSystem() {
-        return template.getTypeSystem();
-    }
-
-    public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror);
-
-    public abstract E create(TemplateMethod method, boolean invalid);
-
-    public abstract boolean isParsable(ExecutableElement method);
-
-    public Class<? extends Annotation> getAnnotationType() {
-        return null;
-    }
-
-    public final List<E> parse(List<? extends Element> elements) {
-        List<ExecutableElement> methods = new ArrayList<>();
-        methods.addAll(ElementFilter.methodsIn(elements));
-
-        List<E> parsedMethods = new ArrayList<>();
-        boolean valid = true;
-        int naturalOrder = 0;
-        for (ExecutableElement method : methods) {
-            if (!isParsable(method)) {
-                continue;
-            }
-
-            Class<? extends Annotation> annotationType = getAnnotationType();
-            AnnotationMirror mirror = null;
-            if (annotationType != null) {
-                mirror = Utils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType);
-            }
-
-            E parsedMethod = parse(naturalOrder, method, mirror);
-
-            if (method.getModifiers().contains(Modifier.PRIVATE) && emitErrors) {
-                parsedMethod.addError("Method annotated with @%s must not be private.", getAnnotationType().getSimpleName());
-                parsedMethods.add(parsedMethod);
-                valid = false;
-                continue;
-            }
-
-            if (parsedMethod != null) {
-                parsedMethods.add(parsedMethod);
-            } else {
-                valid = false;
-            }
-            naturalOrder++;
-        }
-        Collections.sort(parsedMethods);
-
-        if (!valid && parseNullOnError) {
-            return null;
-        }
-        return parsedMethods;
-    }
-
-    private E parse(int naturalOrder, ExecutableElement method, AnnotationMirror annotation) {
-        MethodSpec methodSpecification = createSpecification(method, annotation);
-        if (methodSpecification == null) {
-            return null;
-        }
-
-        methodSpecification.applyTypeDefinitions("types");
-
-        String id = method.getSimpleName().toString();
-        TypeMirror returnType = method.getReturnType();
-        List<TypeMirror> parameterTypes = new ArrayList<>();
-        for (VariableElement var : method.getParameters()) {
-            parameterTypes.add(var.asType());
-        }
-
-        return parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, parameterTypes);
-    }
-
-    private E parseImpl(MethodSpec methodSpecification, int naturalOrder, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType, List<TypeMirror> parameterTypes) {
-        ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
-        ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, template, -1, -1);
-        if (returnTypeMirror == null) {
-            if (emitErrors) {
-                E invalidMethod = create(new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true);
-                String expectedReturnType = returnTypeSpec.toSignatureString(true);
-                String actualReturnType = Utils.getSimpleName(returnType);
-
-                String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
-                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
-                invalidMethod.addError(message);
-                return invalidMethod;
-            } else {
-                return null;
-            }
-        }
-
-        List<ActualParameter> parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method != null ? method.isVarArgs() : false);
-        if (parameters == null) {
-            if (isEmitErrors() && method != null) {
-                E invalidMethod = create(new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true);
-                String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(method),
-                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
-                invalidMethod.addError(message);
-                return invalidMethod;
-            } else {
-                return null;
-            }
-        }
-
-        return create(new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, parameters), false);
-    }
-
-    private static String createActualSignature(ExecutableElement method) {
-        StringBuilder b = new StringBuilder("(");
-        String sep = "";
-        if (method != null) {
-            for (VariableElement var : method.getParameters()) {
-                b.append(sep);
-                b.append(Utils.getSimpleName(var.asType()));
-                sep = ", ";
-            }
-        }
-        b.append(")");
-        return b.toString();
-    }
-
-    /*
-     * Parameter parsing tries to parse required arguments starting from offset 0 with increasing
-     * offset until it finds a signature end that matches the required specification. If there is no
-     * end matching the required arguments, parsing fails. Parameters prior to the parsed required
-     * ones are cut and used to parse the optional parameters.
-     */
-    private List<ActualParameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes, boolean varArgs) {
-        List<ActualParameter> parsedRequired = null;
-        int offset = 0;
-        for (; offset <= parameterTypes.size(); offset++) {
-            List<TypeMirror> parameters = new ArrayList<>();
-            parameters.addAll(parameterTypes.subList(offset, parameterTypes.size()));
-            parsedRequired = parseParametersRequired(spec, parameters, varArgs);
-            if (parsedRequired != null) {
-                break;
-            }
-        }
-
-        if (parsedRequired == null) {
-            return null;
-        }
-
-        if (parsedRequired.isEmpty() && offset == 0) {
-            offset = parameterTypes.size();
-        }
-        List<TypeMirror> potentialOptionals = parameterTypes.subList(0, offset);
-        List<ActualParameter> parsedOptionals = parseParametersOptional(spec, potentialOptionals);
-        if (parsedOptionals == null) {
-            return null;
-        }
-
-        List<ActualParameter> finalParameters = new ArrayList<>();
-        finalParameters.addAll(parsedOptionals);
-        finalParameters.addAll(parsedRequired);
-        return finalParameters;
-    }
-
-    private List<ActualParameter> parseParametersOptional(MethodSpec spec, List<TypeMirror> types) {
-        List<ActualParameter> parsedParams = new ArrayList<>();
-
-        int typeStartIndex = 0;
-        List<ParameterSpec> specifications = spec.getOptional();
-        outer: for (int specIndex = 0; specIndex < specifications.size(); specIndex++) {
-            ParameterSpec specification = specifications.get(specIndex);
-            for (int typeIndex = typeStartIndex; typeIndex < types.size(); typeIndex++) {
-                TypeMirror actualType = types.get(typeIndex);
-                ActualParameter optionalParam = matchParameter(specification, actualType, template, -1, -1);
-                if (optionalParam != null) {
-                    parsedParams.add(optionalParam);
-                    typeStartIndex = typeIndex + 1;
-                    continue outer;
-                }
-            }
-        }
-
-        if (typeStartIndex < types.size()) {
-            // not enough types found
-            return null;
-        }
-        return parsedParams;
-    }
-
-    private List<ActualParameter> parseParametersRequired(MethodSpec spec, List<TypeMirror> types, boolean typeVarArgs) {
-        List<ActualParameter> parsedParams = new ArrayList<>();
-        List<ParameterSpec> specifications = spec.getRequired();
-        boolean specVarArgs = spec.isVariableRequiredParameters();
-        int typeIndex = 0;
-        int specificationIndex = 0;
-
-        ParameterSpec specification;
-        while ((specification = nextSpecification(specifications, specificationIndex, specVarArgs)) != null) {
-            TypeMirror actualType = nextActualType(types, typeIndex, typeVarArgs);
-            if (actualType == null) {
-                if (spec.isIgnoreAdditionalSpecifications()) {
-                    break;
-                }
-                return null;
-            }
-
-            int typeVarArgsIndex = typeVarArgs ? typeIndex - types.size() + 1 : -1;
-            int specVarArgsIndex = specVarArgs ? specificationIndex - specifications.size() + 1 : -1;
-
-            if (typeVarArgsIndex >= 0 && specVarArgsIndex >= 0) {
-                // both specifications and types have a variable number of arguments
-                // we would get into an endless loop if we would continue
-                break;
-            }
-
-            ActualParameter resolvedParameter = matchParameter(specification, actualType, template, specVarArgsIndex, typeVarArgsIndex);
-            if (resolvedParameter == null) {
-                return null;
-            }
-            parsedParams.add(resolvedParameter);
-            typeIndex++;
-            specificationIndex++;
-        }
-
-        if (typeIndex < types.size()) {
-            // additional types available
-            if (spec.isIgnoreAdditionalParameters()) {
-                return parsedParams;
-            } else {
-                return null;
-            }
-        }
-
-        return parsedParams;
-    }
-
-    private static ParameterSpec nextSpecification(List<ParameterSpec> specifications, int specIndex, boolean varArgs) {
-        if (varArgs && specIndex >= specifications.size() - 1 && !specifications.isEmpty()) {
-            return specifications.get(specifications.size() - 1);
-        } else if (specIndex < specifications.size()) {
-            return specifications.get(specIndex);
-        } else {
-            return null;
-        }
-    }
-
-    private static TypeMirror nextActualType(List<TypeMirror> types, int typeIndex, boolean varArgs) {
-        if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) {
-            // unpack varargs array argument
-            TypeMirror actualType = types.get(types.size() - 1);
-            if (actualType.getKind() == TypeKind.ARRAY) {
-                actualType = ((ArrayType) actualType).getComponentType();
-            }
-            return actualType;
-        } else if (typeIndex < types.size()) {
-            return types.get(typeIndex);
-        } else {
-            return null;
-        }
-    }
-
-    protected final ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int specificationIndex, int varArgsIndex) {
-        TypeMirror resolvedType = mirror;
-        if (hasError(resolvedType)) {
-            resolvedType = context.resolveNotYetCompiledType(mirror, originalTemplate);
-        }
-
-        if (!specification.matches(resolvedType)) {
-            return null;
-        }
-
-        TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType);
-        if (resolvedTypeData != null) {
-            return new ActualParameter(specification, resolvedTypeData, specificationIndex, varArgsIndex);
-        } else {
-            return new ActualParameter(specification, resolvedType, specificationIndex, varArgsIndex);
-        }
-    }
-
-    public final E create(String id, int naturalOrder, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List<TypeMirror> parameterTypes) {
-        return parseImpl(createSpecification(methodMetadata, mirror), naturalOrder, id, methodMetadata, mirror, returnType, parameterTypes);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import java.util.*;
-
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class GuardData extends TemplateMethod {
-
-    private List<GuardExpression> impliesExpressions;
-
-    public GuardData(TemplateMethod method, List<GuardExpression> impliesExpressions) {
-        super(method);
-        this.impliesExpressions = impliesExpressions;
-    }
-
-    public List<GuardExpression> getImpliesExpressions() {
-        return impliesExpressions;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof GuardData) {
-            GuardData other = (GuardData) obj;
-            return getMethod().equals(other.getMethod());
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return getMethod().hashCode();
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardExpression.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import java.util.*;
-
-public final class GuardExpression {
-
-    private GuardData resolvedGuard;
-
-    private final String guardName;
-    private final boolean negated;
-
-    public GuardExpression(String expression) {
-        if (expression.startsWith("!")) {
-            guardName = expression.substring(1, expression.length());
-            negated = true;
-        } else {
-            guardName = expression;
-            negated = false;
-        }
-    }
-
-    public boolean isResolved() {
-        return resolvedGuard != null;
-    }
-
-    public String getGuardName() {
-        return guardName;
-    }
-
-    public void setGuard(GuardData guard) {
-        this.resolvedGuard = guard;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof GuardExpression) {
-            GuardExpression other = (GuardExpression) obj;
-            if (isResolved() && other.isResolved()) {
-                return resolvedGuard.equals(other.resolvedGuard) && negated == other.negated;
-            } else {
-                return guardName.equals(other.guardName) && negated == other.negated;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(guardName, negated, resolvedGuard);
-    }
-
-    public int compareConcreteness(GuardExpression other) {
-        if (other == null) {
-            return -1;
-        } else if (this == other) {
-            return 0;
-        }
-
-        /*
-         * Positive and negated guard are always disjunct. So we can choose the positive to be
-         * first.
-         */
-        if (getGuardName().equals(other.getGuardName())) {
-            if (negated == !other.negated) {
-                if (negated) {
-                    return 1;
-                } else {
-                    return -1;
-                }
-            }
-        }
-
-        /*
-         * Very simple version of the implies annotation implementation.
-         */
-        if (isResolved() && other.isResolved()) {
-            if (impliesNot(other)) {
-                return 1;
-            } else if (other.impliesNot(this)) {
-                return -1;
-            }
-        }
-        return 0;
-    }
-
-    public final boolean implies(GuardExpression other) {
-        if (other == this) {
-            return true;
-        }
-        if (getGuardName().equals(other.getGuardName())) {
-            if (isNegated() == other.isNegated()) {
-                return true;
-            }
-        }
-
-        if (isResolved() && other.isResolved()) {
-            for (GuardExpression implies : getResolvedGuard().getImpliesExpressions()) {
-                if (implies.getGuardName().equals(other.getGuardName())) {
-                    if (implies.isNegated() == other.isNegated()) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    public final boolean impliesNot(GuardExpression other) {
-        if (other == this) {
-            return false;
-        }
-        if (getGuardName().equals(other.getGuardName())) {
-            if (isNegated() != other.isNegated()) {
-                return true;
-            }
-        }
-
-        if (isResolved() && other.isResolved()) {
-            for (GuardExpression implies : getResolvedGuard().getImpliesExpressions()) {
-                if (implies.getGuardName().equals(other.getGuardName())) {
-                    if (implies.isNegated() != other.isNegated()) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return (negated ? "!" : "") + guardName;
-    }
-
-    public boolean isNegated() {
-        return negated;
-    }
-
-    public GuardData getResolvedGuard() {
-        return resolvedGuard;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class GuardParser extends NodeMethodParser<GuardData> {
-
-    private final Set<String> guardNames;
-    private final TemplateMethod compatibleSource;
-
-    public GuardParser(ProcessorContext context, NodeData node, TemplateMethod compatibleSource, Set<String> guardNames) {
-        super(context, node);
-        this.guardNames = guardNames;
-        this.compatibleSource = compatibleSource;
-        setEmitErrors(false);
-        setParseNullOnError(false);
-    }
-
-    @Override
-    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
-        return super.createValueParameterSpec(execution);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null);
-        spec.setIgnoreAdditionalSpecifications(true);
-        if (compatibleSource != null) {
-            spec.getRequired().clear();
-            for (ActualParameter parameter : compatibleSource.getRequiredParameters()) {
-                spec.addRequired(new ParameterSpec(parameter.getSpecification(), Utils.getAssignableTypes(getContext(), parameter.getType())));
-            }
-        }
-        return spec;
-    }
-
-    @Override
-    protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
-        Set<TypeMirror> typeMirrors = new LinkedHashSet<>();
-        typeMirrors.addAll(nodeData.getTypeSystem().getPrimitiveTypeMirrors());
-        typeMirrors.addAll(nodeData.getTypeSystem().getBoxedTypeMirrors());
-        return new ArrayList<>(typeMirrors);
-    }
-
-    @Override
-    protected ParameterSpec createReturnParameterSpec() {
-        return new ParameterSpec("returnType", getContext().getType(boolean.class));
-    }
-
-    @Override
-    public boolean isParsable(ExecutableElement method) {
-        return guardNames.contains(method.getSimpleName().toString());
-    }
-
-    @Override
-    public GuardData create(TemplateMethod method, boolean invalid) {
-        Implies impliesAnnotation = method.getMethod().getAnnotation(Implies.class);
-        String[] impliesExpressions = new String[0];
-        if (impliesAnnotation != null) {
-            impliesExpressions = impliesAnnotation.value();
-        }
-        List<GuardExpression> guardExpressions = new ArrayList<>();
-        for (String string : impliesExpressions) {
-            guardExpressions.add(new GuardExpression(string));
-        }
-        return new GuardData(method, guardExpressions);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return null;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class ImplicitCastData extends TemplateMethod {
-
-    private final TypeData sourceType;
-    private final TypeData targetType;
-
-    public ImplicitCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) {
-        super(method);
-        this.sourceType = sourceType;
-        this.targetType = targetType;
-    }
-
-    public TypeData getSourceType() {
-        return sourceType;
-    }
-
-    public TypeData getTargetType() {
-        return targetType;
-    }
-
-    @Override
-    public int compareTo(TemplateMethod o) {
-        if (o instanceof ImplicitCastData && sourceType != null) {
-            // implicit casts are ordered by source type since
-            // its also the order in which they are checked.
-            TypeData otherSourceType = ((ImplicitCastData) o).getSourceType();
-            if (otherSourceType != null) {
-                return this.sourceType.compareTo(otherSourceType);
-            }
-        }
-        return super.compareTo(o);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java	Mon Aug 11 15:53:05 2014 +0200
+++ /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.dsl.processor.typesystem;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class ImplicitCastParser extends TypeSystemMethodParser<ImplicitCastData> {
-
-    public ImplicitCastParser(ProcessorContext context, TypeSystemData typeSystem) {
-        super(context, typeSystem);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return ImplicitCast.class;
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        List<TypeMirror> types = new ArrayList<>();
-        for (TypeData typeData : getTypeSystem().getTypes()) {
-            types.add(typeData.getPrimitiveType());
-        }
-        MethodSpec spec = new MethodSpec(new ParameterSpec("target", types));
-        spec.addRequired(new ParameterSpec("source", types));
-        return spec;
-    }
-
-    @Override
-    public ImplicitCastData create(TemplateMethod method, boolean invalid) {
-        if (invalid) {
-            return new ImplicitCastData(method, null, null);
-        }
-
-        ActualParameter target = method.findParameter("targetValue");
-        ActualParameter source = method.findParameter("sourceValue");
-
-        TypeData targetType = target.getTypeSystemType();
-        TypeData sourceType = source.getTypeSystemType();
-
-        if (targetType.equals(sourceType)) {
-            method.addError("Target type and source type of an @%s must not be the same type.", ImplicitCast.class.getSimpleName());
-        }
-
-        return new ImplicitCastData(method, sourceType, targetType);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class TypeCastData extends TemplateMethod {
-
-    private final TypeData targetType;
-    private final TypeData sourceType;
-
-    public TypeCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) {
-        super(method);
-        this.sourceType = sourceType;
-        this.targetType = targetType;
-    }
-
-    public boolean isGeneric() {
-        return sourceType.isGeneric();
-    }
-
-    public TypeData getSourceType() {
-        return sourceType;
-    }
-
-    public TypeData getTargetType() {
-        return targetType;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import java.lang.annotation.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-class TypeCastParser extends TypeSystemMethodParser<TypeCastData> {
-
-    public TypeCastParser(ProcessorContext context, TypeSystemData typeSystem) {
-        super(context, typeSystem);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "as");
-        if (targetType == null) {
-            return null;
-        }
-        MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", targetType.getPrimitiveType()));
-        spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors()));
-        return spec;
-    }
-
-    @Override
-    public TypeCastData create(TemplateMethod method, boolean invalid) {
-        if (invalid) {
-            return new TypeCastData(method, null, null);
-        }
-
-        TypeData targetType = findTypeByMethodName(method, "as");
-        ActualParameter parameter = method.findParameter("valueValue");
-
-        TypeData sourceType = null;
-        if (parameter != null) {
-            sourceType = getTypeSystem().findTypeData(parameter.getType());
-        }
-        TypeCastData cast = new TypeCastData(method, sourceType, targetType);
-
-        if (targetType != method.getReturnType().getTypeSystemType()) {
-            cast.addError("Cast type %s does not match to the returned type %s.", Utils.getSimpleName(targetType.getPrimitiveType()),
-                            method.getReturnType() != null ? Utils.getSimpleName(method.getReturnType().getTypeSystemType().getPrimitiveType()) : null);
-        }
-        return cast;
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return TypeCast.class;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class TypeCheckData extends TemplateMethod {
-
-    private final TypeData checkedType;
-    private final TypeData valueType;
-
-    public TypeCheckData(TemplateMethod method, TypeData checkedType, TypeData valueType) {
-        super(method);
-        this.checkedType = checkedType;
-        this.valueType = valueType;
-    }
-
-    public boolean isGeneric() {
-        return valueType.isGeneric();
-    }
-
-    public TypeData getCheckedType() {
-        return checkedType;
-    }
-
-    public TypeData getValueType() {
-        return valueType;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import java.lang.annotation.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-class TypeCheckParser extends TypeSystemMethodParser<TypeCheckData> {
-
-    public TypeCheckParser(ProcessorContext context, TypeSystemData typeSystem) {
-        super(context, typeSystem);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "is");
-        if (targetType == null) {
-            return null;
-        }
-        MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", getContext().getType(boolean.class)));
-        spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors()));
-        return spec;
-    }
-
-    @Override
-    public TypeCheckData create(TemplateMethod method, boolean invalid) {
-        TypeData checkedType = findTypeByMethodName(method, "is");
-        assert checkedType != null;
-        ActualParameter parameter = method.findParameter("valueValue");
-        assert parameter != null;
-        return new TypeCheckData(method, checkedType, parameter.getTypeSystemType());
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return TypeCheck.class;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class TypeData extends MessageContainer implements Comparable<TypeData> {
-
-    private final TypeSystemData typeSystem;
-    private final AnnotationValue annotationValue;
-    private final TypeMirror primitiveType;
-    private final TypeMirror boxedType;
-
-    private final int index;
-    private final List<TypeCastData> typeCasts = new ArrayList<>();
-    private final List<TypeCheckData> typeChecks = new ArrayList<>();
-
-    public TypeData(TypeSystemData typeSystem, int index, AnnotationValue value, TypeMirror primitiveType, TypeMirror boxedType) {
-        this.index = index;
-        this.typeSystem = typeSystem;
-        this.annotationValue = value;
-        this.primitiveType = primitiveType;
-        this.boxedType = boxedType;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return typeSystem.getMessageElement();
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return typeSystem.getMessageAnnotation();
-    }
-
-    @Override
-    public AnnotationValue getMessageAnnotationValue() {
-        return annotationValue;
-    }
-
-    void addTypeCast(TypeCastData typeCast) {
-        this.typeCasts.add(typeCast);
-    }
-
-    void addTypeCheck(TypeCheckData typeCheck) {
-        this.typeChecks.add(typeCheck);
-    }
-
-    public List<TypeCastData> getTypeCasts() {
-        return typeCasts;
-    }
-
-    public List<TypeCheckData> getTypeChecks() {
-        return typeChecks;
-    }
-
-    public TypeSystemData getTypeSystem() {
-        return typeSystem;
-    }
-
-    public TypeMirror getPrimitiveType() {
-        return primitiveType;
-    }
-
-    public TypeMirror getBoxedType() {
-        return boxedType;
-    }
-
-    public boolean isGeneric() {
-        return Utils.typeEquals(boxedType, getTypeSystem().getGenericType());
-    }
-
-    public boolean isVoid() {
-        if (getTypeSystem().getVoidType() == null) {
-            return false;
-        }
-        return Utils.typeEquals(boxedType, getTypeSystem().getVoidType().getBoxedType());
-    }
-
-    public int compareTo(TypeData o) {
-        if (this.equals(o)) {
-            return 0;
-        }
-        return index - o.index;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(index, primitiveType);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof TypeData)) {
-            return false;
-        }
-        TypeData otherType = (TypeData) obj;
-        return index == otherType.index && Utils.typeEquals(primitiveType, otherType.primitiveType);
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + "[" + Utils.getSimpleName(primitiveType) + "]";
-    }
-
-    public boolean equalsType(TypeData actualTypeData) {
-        return Utils.typeEquals(boxedType, actualTypeData.boxedType);
-    }
-
-    public boolean needsCastTo(TypeData targetType) {
-        return Utils.needsCastTo(getPrimitiveType(), targetType.getPrimitiveType());
-    }
-
-    public boolean needsCastTo(TypeMirror targetType) {
-        return Utils.needsCastTo(getPrimitiveType(), targetType);
-    }
-
-    public boolean isPrimitive() {
-        return Utils.isPrimitive(getPrimitiveType());
-    }
-
-    public boolean isImplicitSubtypeOf(TypeData other) {
-        List<ImplicitCastData> casts = other.getTypeSystem().lookupByTargetType(other);
-        for (ImplicitCastData cast : casts) {
-            if (isSubtypeOf(cast.getSourceType())) {
-                return true;
-            }
-        }
-        return isSubtypeOf(other);
-    }
-
-    public boolean isSubtypeOf(TypeData other) {
-        return Utils.isSubtype(boxedType, other.boxedType);
-    }
-
-    public boolean intersects(TypeData type) {
-        if (this.equals(type)) {
-            return true;
-        }
-        if (type.isGeneric() || isGeneric()) {
-            return true;
-        }
-        return isSubtypeOf(type) || type.isSubtypeOf(this);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,300 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import static com.oracle.truffle.dsl.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.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.ast.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class TypeSystemCodeGenerator extends CompilationUnitFactory<TypeSystemData> {
-
-    public static String isTypeMethodName(TypeData type) {
-        return "is" + Utils.getTypeId(type.getBoxedType());
-    }
-
-    public static String isImplicitTypeMethodName(TypeData type) {
-        return "isImplicit" + Utils.getTypeId(type.getBoxedType());
-    }
-
-    public static String asTypeMethodName(TypeData type) {
-        return "as" + Utils.getTypeId(type.getBoxedType());
-    }
-
-    public static String asImplicitTypeMethodName(TypeData type) {
-        return "asImplicit" + Utils.getTypeId(type.getBoxedType());
-    }
-
-    public static String getImplicitClass(TypeData type) {
-        return "getImplicit" + Utils.getTypeId(type.getBoxedType()) + "Class";
-    }
-
-    public static String expectTypeMethodName(TypeData type) {
-        return "expect" + Utils.getTypeId(type.getBoxedType());
-    }
-
-    public static String typeName(TypeSystemData typeSystem) {
-        String name = getSimpleName(typeSystem.getTemplateType());
-        return name + "Gen";
-    }
-
-    public static String singletonName(TypeSystemData type) {
-        return createConstantName(getSimpleName(type.getTemplateType().asType()));
-    }
-
-    /**
-     * Finds the generated singleton field for a TypeSytemData instance. TypeSystemCodeGenerator
-     * must be applied to the TypeSystemData model before use.
-     */
-    public static VariableElement findSingleton(ProcessorContext context, TypeSystemData typeSystem) {
-        TypeMirror type = context.findGeneratedClassBySimpleName(typeName(typeSystem), typeSystem);
-        return Utils.findDeclaredField(type, singletonName(typeSystem));
-    }
-
-    @Override
-    protected void createChildren(TypeSystemData m) {
-        add(new TypeClassFactory(), m);
-    }
-
-    protected static class TypeClassFactory extends ClassElementFactory<TypeSystemData> {
-
-        private static final String LOCAL_VALUE = "value";
-
-        @Override
-        public CodeTypeElement create(TypeSystemData typeSystem) {
-            String name = typeName(typeSystem);
-            CodeTypeElement clazz = createClass(typeSystem, modifiers(PUBLIC, FINAL), name, typeSystem.getTemplateType().asType(), false);
-
-            clazz.add(createConstructorUsingFields(modifiers(PROTECTED), clazz));
-            CodeVariableElement singleton = createSingleton(clazz);
-            clazz.add(singleton);
-
-            for (TypeData type : typeSystem.getTypes()) {
-                if (!type.isGeneric()) {
-                    clazz.addOptional(createIsTypeMethod(type));
-                    clazz.addOptional(createAsTypeMethod(type));
-
-                    for (TypeData sourceType : collectExpectSourceTypes(type)) {
-                        clazz.addOptional(createExpectTypeMethod(type, sourceType));
-                    }
-
-                    clazz.addOptional(createAsImplicitTypeMethod(type, true));
-                    clazz.addOptional(createAsImplicitTypeMethod(type, false));
-                    clazz.addOptional(createIsImplicitTypeMethod(type, true));
-                    clazz.addOptional(createIsImplicitTypeMethod(type, false));
-                    clazz.addOptional(createGetTypeIndex(type));
-                }
-            }
-
-            return clazz;
-        }
-
-        private static List<TypeData> collectExpectSourceTypes(TypeData type) {
-            Set<TypeData> sourceTypes = new HashSet<>();
-            sourceTypes.add(type.getTypeSystem().getGenericTypeData());
-            for (TypeCastData cast : type.getTypeCasts()) {
-                sourceTypes.add(cast.getSourceType());
-            }
-            for (TypeCheckData cast : type.getTypeChecks()) {
-                sourceTypes.add(cast.getCheckedType());
-            }
-            return new ArrayList<>(sourceTypes);
-        }
-
-        private CodeVariableElement createSingleton(CodeTypeElement clazz) {
-            CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(getModel()));
-            field.createInitBuilder().startNew(clazz.asType()).end();
-            return field;
-        }
-
-        private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) {
-            TypeSystemData typeSystem = getModel();
-            List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
-            if (casts.isEmpty()) {
-                return null;
-            }
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type));
-            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
-            if (typed) {
-                method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint"));
-            }
-            CodeTreeBuilder builder = method.createBuilder();
-
-            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
-
-            builder.startReturn();
-            String sep = "";
-            for (TypeData sourceType : sourceTypes) {
-                builder.string(sep);
-                if (typed) {
-                    builder.string("(typeHint == ").typeLiteral(sourceType.getPrimitiveType()).string(" && ");
-                }
-                builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end();
-                if (typed) {
-                    builder.string(")");
-                }
-                if (sourceTypes.lastIndexOf(sourceType) != sourceTypes.size() - 1) {
-                    builder.newLine();
-                }
-                if (sep.equals("")) {
-                    builder.startIndention();
-                }
-                sep = " || ";
-            }
-            builder.end();
-            builder.end();
-            return method;
-        }
-
-        private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean typed) {
-            TypeSystemData typeSystem = getModel();
-            List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
-            if (casts.isEmpty()) {
-                return null;
-            }
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asImplicitTypeMethodName(type));
-            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
-            if (typed) {
-                method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint"));
-            }
-
-            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
-
-            CodeTreeBuilder builder = method.createBuilder();
-            boolean elseIf = false;
-            for (TypeData sourceType : sourceTypes) {
-                elseIf = builder.startIf(elseIf);
-                if (typed) {
-                    builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType());
-                } else {
-                    builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end();
-                }
-
-                builder.end().startBlock();
-
-                builder.startReturn();
-                ImplicitCastData cast = typeSystem.lookupCast(sourceType, type);
-                if (cast != null) {
-                    builder.startCall(cast.getMethodName());
-                }
-                builder.startCall(asTypeMethodName(sourceType)).string(LOCAL_VALUE).end();
-                if (cast != null) {
-                    builder.end();
-                }
-                builder.end();
-                builder.end();
-            }
-
-            builder.startElseBlock();
-            builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
-            builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
-            builder.end();
-            return method;
-        }
-
-        private CodeExecutableElement createGetTypeIndex(TypeData type) {
-            TypeSystemData typeSystem = getModel();
-            List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
-            if (casts.isEmpty()) {
-                return null;
-            }
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(type));
-            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
-
-            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
-            CodeTreeBuilder builder = method.createBuilder();
-            boolean elseIf = false;
-            for (TypeData sourceType : sourceTypes) {
-                elseIf = builder.startIf(elseIf);
-                builder.startCall(isTypeMethodName(sourceType)).string(LOCAL_VALUE).end();
-                builder.end().startBlock();
-                builder.startReturn().typeLiteral(sourceType.getPrimitiveType()).end();
-                builder.end();
-            }
-
-            builder.startElseBlock();
-            builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
-            builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
-            builder.end();
-
-            return method;
-        }
-
-        private CodeExecutableElement createIsTypeMethod(TypeData type) {
-            if (!type.getTypeChecks().isEmpty()) {
-                return null;
-            }
-
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(type));
-            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
-
-            DeclaredType suppressWarnings = (DeclaredType) getContext().getType(SuppressWarnings.class);
-            CodeAnnotationMirror annotationMirror = new CodeAnnotationMirror(suppressWarnings);
-            annotationMirror.setElementValue(annotationMirror.findExecutableElement("value"), new CodeAnnotationValue("static-method"));
-            method.getAnnotationMirrors().add(annotationMirror);
-
-            CodeTreeBuilder body = method.createBuilder();
-            body.startReturn().instanceOf(LOCAL_VALUE, type.getBoxedType()).end();
-
-            return method;
-        }
-
-        private CodeExecutableElement createAsTypeMethod(TypeData type) {
-            if (!type.getTypeCasts().isEmpty()) {
-                return null;
-            }
-
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asTypeMethodName(type));
-            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
-
-            CodeTreeBuilder body = method.createBuilder();
-            String assertMessage = typeName(getModel()) + "." + asTypeMethodName(type) + ": " + Utils.getSimpleName(type.getBoxedType()) + " expected";
-            body.startAssert().startCall(isTypeMethodName(type)).string(LOCAL_VALUE).end().string(" : ").doubleQuote(assertMessage).end();
-            body.startReturn().cast(type.getPrimitiveType(), body.create().string(LOCAL_VALUE).getTree()).end();
-
-            return method;
-        }
-
-        private CodeExecutableElement createExpectTypeMethod(TypeData expectedType, TypeData sourceType) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), expectedType.getPrimitiveType(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType));
-            method.addParameter(new CodeVariableElement(sourceType.getPrimitiveType(), LOCAL_VALUE));
-            method.addThrownType(getContext().getTruffleTypes().getUnexpectedValueException());
-
-            CodeTreeBuilder body = method.createBuilder();
-            body.startIf().startCall(TypeSystemCodeGenerator.isTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end().startBlock();
-            body.startReturn().startCall(TypeSystemCodeGenerator.asTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end();
-            body.end(); // if-block
-            body.startThrow().startNew(getContext().getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end();
-
-            return method;
-        }
-
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class TypeSystemData extends Template {
-
-    private List<TypeData> types;
-    private List<TypeMirror> primitiveTypeMirrors = new ArrayList<>();
-    private List<TypeMirror> boxedTypeMirrors = new ArrayList<>();
-
-    private List<ImplicitCastData> implicitCasts;
-    private List<TypeCastData> casts;
-    private List<TypeCheckData> checks;
-
-    private TypeMirror genericType;
-    private TypeData voidType;
-
-    public TypeSystemData(ProcessorContext context, TypeElement templateType, AnnotationMirror annotation) {
-        super(context, templateType, null, annotation);
-    }
-
-    @Override
-    public TypeSystemData getTypeSystem() {
-        return this;
-    }
-
-    void setTypes(List<TypeData> types) {
-        this.types = types;
-        if (types != null) {
-            for (TypeData typeData : types) {
-                primitiveTypeMirrors.add(typeData.getPrimitiveType());
-                boxedTypeMirrors.add(typeData.getBoxedType());
-            }
-        }
-    }
-
-    public void setImplicitCasts(List<ImplicitCastData> implicitCasts) {
-        this.implicitCasts = implicitCasts;
-    }
-
-    public List<ImplicitCastData> getImplicitCasts() {
-        return implicitCasts;
-    }
-
-    public void setCasts(List<TypeCastData> casts) {
-        this.casts = casts;
-    }
-
-    public void setChecks(List<TypeCheckData> checks) {
-        this.checks = checks;
-    }
-
-    void setGenericType(TypeMirror genericType) {
-        this.genericType = genericType;
-    }
-
-    void setVoidType(TypeData voidType) {
-        this.voidType = voidType;
-    }
-
-    @Override
-    protected List<MessageContainer> findChildContainers() {
-        List<MessageContainer> sinks = new ArrayList<>();
-        if (types != null) {
-            sinks.addAll(types);
-        }
-        if (checks != null) {
-            sinks.addAll(checks);
-        }
-        if (casts != null) {
-            sinks.addAll(casts);
-        }
-        if (implicitCasts != null) {
-            sinks.addAll(implicitCasts);
-        }
-        return sinks;
-    }
-
-    public boolean isGeneric(TypeMirror type) {
-        return Utils.typeEquals(getGenericType(), type);
-    }
-
-    public TypeData getVoidType() {
-        return voidType;
-    }
-
-    public List<TypeMirror> getBoxedTypeMirrors() {
-        return boxedTypeMirrors;
-    }
-
-    public List<TypeMirror> getPrimitiveTypeMirrors() {
-        return primitiveTypeMirrors;
-    }
-
-    public List<TypeData> getTypes() {
-        return types;
-    }
-
-    public TypeMirror getGenericType() {
-        return genericType;
-    }
-
-    public TypeData getGenericTypeData() {
-        TypeData result = types.get(types.size() - 1);
-        assert result.getBoxedType() == genericType;
-        return result;
-    }
-
-    public TypeData findType(String simpleName) {
-        for (TypeData type : types) {
-            if (Utils.getSimpleName(type.getBoxedType()).equals(simpleName)) {
-                return type;
-            }
-        }
-        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.get(index);
-    }
-
-    public int findType(TypeData typeData) {
-        return findType(typeData.getPrimitiveType());
-    }
-
-    public int findType(TypeMirror type) {
-        for (int i = 0; i < types.size(); i++) {
-            if (Utils.typeEquals(types.get(i).getPrimitiveType(), type)) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + "[template = " + Utils.getSimpleName(getTemplateType()) + ", types = " + types + "]";
-    }
-
-    public Set<TypeData> lookupCastSourceTypes() {
-        if (getImplicitCasts() == null) {
-            return null;
-        }
-
-        Set<TypeData> sourceTypes = new TreeSet<>();
-        for (ImplicitCastData cast : getImplicitCasts()) {
-            sourceTypes.add(cast.getSourceType());
-        }
-        return sourceTypes;
-    }
-
-    public List<ImplicitCastData> lookupByTargetType(TypeData targetType) {
-        if (getImplicitCasts() == null) {
-            return Collections.emptyList();
-        }
-        List<ImplicitCastData> foundCasts = new ArrayList<>();
-        for (ImplicitCastData cast : getImplicitCasts()) {
-            if (cast.getTargetType().equals(targetType)) {
-                foundCasts.add(cast);
-            }
-        }
-        return foundCasts;
-    }
-
-    public ImplicitCastData lookupCast(TypeData sourceType, TypeData targetType) {
-        if (getImplicitCasts() == null) {
-            return null;
-        }
-        for (ImplicitCastData cast : getImplicitCasts()) {
-            if (cast.getSourceType().equals(sourceType) && cast.getTargetType().equals(targetType)) {
-                return cast;
-            }
-        }
-        return null;
-    }
-
-    public List<TypeData> lookupSourceTypes(TypeData type) {
-        List<TypeData> sourceTypes = new ArrayList<>();
-        sourceTypes.add(type);
-        if (getImplicitCasts() != null) {
-            for (ImplicitCastData cast : getImplicitCasts()) {
-                if (cast.getTargetType() == type) {
-                    sourceTypes.add(cast.getSourceType());
-                }
-            }
-        }
-        Collections.sort(sourceTypes);
-        return sourceTypes;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemMethodParser.java	Mon Aug 11 15:53:05 2014 +0200
+++ /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.dsl.processor.typesystem;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-abstract class TypeSystemMethodParser<E extends TemplateMethod> extends TemplateMethodParser<TypeSystemData, E> {
-
-    public TypeSystemMethodParser(ProcessorContext context, TypeSystemData typeSystem) {
-        super(context, typeSystem);
-    }
-
-    @Override
-    public final boolean isParsable(ExecutableElement method) {
-        return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
-    }
-
-    protected TypeData findTypeByMethodName(String methodName, String prefix) {
-        String typeName = methodName.substring(prefix.length(), methodName.length());
-        TypeData type = getTypeSystem().findType(typeName);
-        return type;
-    }
-
-    protected TypeData findTypeByMethodName(TemplateMethod method, String prefix) {
-        String methodName = method.getMethodName();
-        if (!methodName.startsWith(prefix)) {
-            String annotationName = Utils.getSimpleName(method.getMessageAnnotation().getAnnotationType());
-            method.addError("Methods annotated with %s must match the pattern '%s'.", annotationName, String.format("%s${typeName}", prefix));
-            return null;
-        }
-        String typeName = methodName.substring(prefix.length(), methodName.length());
-        TypeData type = getTypeSystem().findType(typeName);
-        if (type == null) {
-            String annotationName = TypeSystem.class.getSimpleName();
-            method.addError("Type '%s' is not declared in this @%s.", typeName, annotationName);
-            return null;
-        }
-
-        return type;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,305 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.typesystem;
-
-import static com.oracle.truffle.dsl.processor.Utils.*;
-
-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.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.*;
-
-public class TypeSystemParser extends AbstractParser<TypeSystemData> {
-
-    public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(TypeSystem.class, ExpectError.class);
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return TypeSystem.class;
-    }
-
-    @Override
-    protected TypeSystemData parse(Element element, AnnotationMirror mirror) {
-        TypeElement templateType = (TypeElement) element;
-        AnnotationMirror templateTypeAnnotation = mirror;
-        TypeSystemData typeSystem = new TypeSystemData(context, templateType, templateTypeAnnotation);
-
-        // annotation type on class path!?
-        TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName());
-        if (annotationTypeElement == null) {
-            typeSystem.addError("Required class %s is not on the classpath.", getAnnotationType().getName());
-        }
-        if (templateType.getModifiers().contains(Modifier.PRIVATE)) {
-            typeSystem.addError("A @%s must have at least package protected visibility.", getAnnotationType().getName());
-        }
-
-        if (templateType.getModifiers().contains(Modifier.FINAL)) {
-            typeSystem.addError("The @%s must not be final.", getAnnotationType().getName());
-        }
-        if (typeSystem.hasErrors()) {
-            return typeSystem;
-        }
-
-        typeSystem.setTypes(parseTypes(typeSystem));
-        if (typeSystem.hasErrors()) {
-            return typeSystem;
-        }
-
-        TypeMirror genericType = context.getType(Object.class);
-        TypeData voidType = new TypeData(typeSystem, typeSystem.getTypes().size(), null, context.getType(void.class), context.getType(Void.class));
-
-        typeSystem.setGenericType(genericType);
-        typeSystem.setVoidType(voidType);
-
-        verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class);
-
-        List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType));
-        List<ImplicitCastData> implicitCasts = new ImplicitCastParser(context, typeSystem).parse(elements);
-        List<TypeCastData> casts = new TypeCastParser(context, typeSystem).parse(elements);
-        List<TypeCheckData> checks = new TypeCheckParser(context, typeSystem).parse(elements);
-
-        if (casts == null || checks == null || implicitCasts == null) {
-            return typeSystem;
-        }
-
-        typeSystem.setImplicitCasts(implicitCasts);
-        typeSystem.setCasts(casts);
-        typeSystem.setChecks(checks);
-
-        if (typeSystem.hasErrors()) {
-            return typeSystem;
-        }
-
-        for (TypeCheckData check : checks) {
-            check.getCheckedType().addTypeCheck(check);
-        }
-
-        for (TypeCastData cast : casts) {
-            cast.getTargetType().addTypeCast(cast);
-        }
-
-        verifyGenericTypeChecksAndCasts(typeSystem);
-        verifyMethodSignatures(typeSystem);
-        verifyNamesUnique(typeSystem);
-
-        return typeSystem;
-    }
-
-    protected void verifyExclusiveMethodAnnotation(Template template, Class<?>... annotationTypes) {
-        List<ExecutableElement> methods = ElementFilter.methodsIn(template.getTemplateType().getEnclosedElements());
-        for (ExecutableElement method : methods) {
-            List<AnnotationMirror> foundAnnotations = new ArrayList<>();
-            for (int i = 0; i < annotationTypes.length; i++) {
-                Class<?> annotationType = annotationTypes[i];
-                AnnotationMirror mirror = Utils.findAnnotationMirror(context.getEnvironment(), method, annotationType);
-                if (mirror != null) {
-                    foundAnnotations.add(mirror);
-                }
-            }
-            if (foundAnnotations.size() > 1) {
-                List<String> annotationNames = new ArrayList<>();
-                for (AnnotationMirror mirror : foundAnnotations) {
-                    annotationNames.add("@" + Utils.getSimpleName(mirror.getAnnotationType()));
-                }
-
-                template.addError("Non exclusive usage of annotations %s.", annotationNames);
-            }
-        }
-    }
-
-    private static void verifyGenericTypeChecksAndCasts(TypeSystemData typeSystem) {
-        for (TypeData type : typeSystem.getTypes()) {
-            if (!type.getTypeChecks().isEmpty()) {
-                boolean hasGeneric = false;
-                for (TypeCheckData typeCheck : type.getTypeChecks()) {
-                    if (typeCheck.isGeneric()) {
-                        hasGeneric = true;
-                        break;
-                    }
-                }
-                if (!hasGeneric) {
-                    type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.",
-                                    TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(),
-                                    Object.class.getSimpleName());
-                }
-            }
-            if (!type.getTypeCasts().isEmpty()) {
-                boolean hasGeneric = false;
-                for (TypeCastData typeCast : type.getTypeCasts()) {
-                    if (typeCast.isGeneric()) {
-                        hasGeneric = true;
-                        break;
-                    }
-                }
-                if (!hasGeneric) {
-                    type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.",
-                                    TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(),
-                                    Object.class.getSimpleName());
-                }
-            }
-        }
-    }
-
-    private List<TypeData> parseTypes(TypeSystemData typeSystem) {
-        List<TypeData> types = new ArrayList<>();
-        List<TypeMirror> typeMirrors = Utils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value");
-        if (typeMirrors.isEmpty()) {
-            typeSystem.addError("At least one type must be defined.");
-            return types;
-        }
-
-        final AnnotationValue annotationValue = Utils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "value");
-        final TypeMirror objectType = context.getType(Object.class);
-
-        int index = 0;
-        for (TypeMirror primitiveType : typeMirrors) {
-            TypeMirror boxedType = Utils.boxType(context, primitiveType);
-            TypeData typeData = new TypeData(typeSystem, index, annotationValue, primitiveType, boxedType);
-
-            if (isPrimitiveWrapper(primitiveType)) {
-                typeData.addError("Types must not contain primitive wrapper types.");
-            }
-
-            if (Utils.typeEquals(boxedType, objectType)) {
-                typeData.addError("Types must not contain the generic type java.lang.Object.");
-            }
-
-            types.add(typeData);
-            index++;
-        }
-
-        verifyTypeOrder(types);
-
-        types.add(new TypeData(typeSystem, index, annotationValue, objectType, objectType));
-
-        return types;
-    }
-
-    private static void verifyTypeOrder(List<TypeData> types) {
-        Map<String, List<String>> invalidTypes = new HashMap<>();
-
-        for (int i = types.size() - 1; i >= 0; i--) {
-            TypeData typeData = types.get(i);
-            TypeMirror type = typeData.getBoxedType();
-            if (invalidTypes.containsKey(Utils.getQualifiedName(type))) {
-                typeData.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(Utils.getQualifiedName(type)), Utils.getQualifiedName(type));
-            }
-            List<String> nextInvalidTypes = Utils.getQualifiedSuperTypeNames(Utils.fromTypeMirror(type));
-            nextInvalidTypes.add(getQualifiedName(type));
-
-            for (String qualifiedName : nextInvalidTypes) {
-                List<String> inheritedTypes = invalidTypes.get(qualifiedName);
-                if (inheritedTypes == null) {
-                    inheritedTypes = new ArrayList<>();
-                    invalidTypes.put(qualifiedName, inheritedTypes);
-                }
-                inheritedTypes.add(Utils.getQualifiedName(typeData.getBoxedType()));
-            }
-        }
-    }
-
-    private boolean isPrimitiveWrapper(TypeMirror type) {
-        Types types = context.getEnvironment().getTypeUtils();
-        for (TypeKind kind : TypeKind.values()) {
-            if (!kind.isPrimitive()) {
-                continue;
-            }
-            if (Utils.typeEquals(type, types.boxedClass(types.getPrimitiveType(kind)).asType())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private void verifyMethodSignatures(TypeSystemData typeSystem) {
-        Set<String> generatedIsMethodNames = new HashSet<>();
-        Set<String> generatedAsMethodNames = new HashSet<>();
-        Set<String> generatedExpectMethodNames = new HashSet<>();
-
-        for (TypeData typeData : typeSystem.getTypes()) {
-            generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData));
-            generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData));
-            generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData));
-        }
-
-        List<ExecutableElement> methods = ElementFilter.methodsIn(typeSystem.getTemplateType().getEnclosedElements());
-        for (ExecutableElement method : methods) {
-            if (method.getModifiers().contains(Modifier.PRIVATE)) {
-                // will not conflict overridden methods
-                continue;
-            } else if (method.getParameters().size() != 1) {
-                continue;
-            }
-            String methodName = method.getSimpleName().toString();
-            if (generatedIsMethodNames.contains(methodName)) {
-                verifyIsMethod(typeSystem, method);
-            } else if (generatedAsMethodNames.contains(methodName)) {
-                verifyAsMethod(typeSystem, method);
-            } else if (generatedExpectMethodNames.contains(methodName)) {
-                verifyExpectMethod(typeSystem);
-            }
-        }
-    }
-
-    private boolean verifyIsMethod(TypeSystemData typeSystem, ExecutableElement method) {
-        AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCheck.class);
-        if (mirror == null) {
-            typeSystem.addError("Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName());
-            return false;
-        }
-        return true;
-    }
-
-    private boolean verifyAsMethod(TypeSystemData typeSystem, ExecutableElement method) {
-        AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCast.class);
-        if (mirror == null) {
-            typeSystem.addError("Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName());
-            return false;
-        }
-        return true;
-    }
-
-    private static boolean verifyExpectMethod(TypeSystemData typeSystem) {
-        typeSystem.addError("Method starting with the pattern expect${typeName} must not be declared manually.");
-        return false;
-    }
-
-    private static void verifyNamesUnique(TypeSystemData typeSystem) {
-        List<TypeData> types = typeSystem.getTypes();
-        for (int i = 0; i < types.size(); i++) {
-            for (int j = i + 1; j < types.size(); j++) {
-                String name1 = Utils.getSimpleName(types.get(i).getBoxedType());
-                String name2 = Utils.getSimpleName(types.get(j).getBoxedType());
-                if (name1.equalsIgnoreCase(name2)) {
-                    typeSystem.addError("Two types result in the same name: %s, %s.", name1, name2);
-                }
-            }
-        }
-    }
-}