changeset 7291:a748e4d44694

Truffle API to specify type-specalized Node classes; annotation processor for automatic code generation of the type-specialized Node classes during the build process
author Christian Humer <christian.humer@gmail.com>
date Fri, 21 Dec 2012 10:44:31 -0800
parents a81db08fe930
children 213c1297a814
files .hgignore graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ExtensionAnnotation.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GeneratedBy.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Generic.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GuardCheck.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Operation.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ShortCircuit.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Specialization.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationGuard.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationListener.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationThrows.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCast.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCheck.java graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java graal/com.oracle.truffle.codegen.processor/src/META-INF/services/javax.annotation.processing.Processor graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AnnotationProcessor.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ProcessorContext.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/ExtensionContext.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/ExtensionProcessor.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableAnnotationMirror.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableElement.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableElementFactory.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableExecutableElement.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableVariableElement.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationMirror.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationValue.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeCompilationUnit.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElementScanner.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeImport.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeNames.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTree.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeKind.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeElement.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeVariableElement.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/GeneratedElement.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/FixWarningsVisitor.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/GenerateOverrideVisitor.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/AbstractCompiler.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/Compiler.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/CompilerFactory.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JDTCompiler.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JavaCCompiler.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionCodeElementFactory.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionContextImpl.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/GenericParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationCodeGenerator.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationFieldData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationMethodParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/ShortCircuitData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/ShortCircuitParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationGuardData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationListenerParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationThrowsData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CodeElementFactory.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CompilationUnitFactory.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/JavaName.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/Template.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java mx/commands.py mx/projects mxtool/mx.py
diffstat 94 files changed, 11189 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Fri Dec 21 10:21:24 2012 +0100
+++ b/.hgignore	Fri Dec 21 10:44:31 2012 -0800
@@ -12,6 +12,8 @@
 ^work/
 \.checkstyle$
 \.classpath
+\.factorypath
+\.externalToolBuilders
 \.project
 \.settings/
 \.metadata/
@@ -43,6 +45,7 @@
 ^test-output/
 scratch/
 bin/
+src_gen/
 ^local/
 ^src/share/tools/hsdis/build/
 ^src/share/tools/IdealGraphVisualizer/[a-zA-Z0-9]*/build/
@@ -59,3 +62,7 @@
 syntax: glob
 *.bgv
 core.*
+*.jar
+eclipse-build.xml
+rebuild-launch.out
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ExtensionAnnotation.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.ANNOTATION_TYPE})
+public @interface ExtensionAnnotation {
+
+    String processorClassName();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GeneratedBy.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+/**
+ * Marks a type to be generated by another class.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+public @interface GeneratedBy {
+
+    Class< ? > value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Generic.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+/**
+ *
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface Generic {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GuardCheck.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+/**
+ * 
+ *
+ * @see SpecializationGuard
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface GuardCheck {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Operation.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.api.codegen;
+
+import java.lang.annotation.*;
+import com.oracle.truffle.api.nodes.*;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+public @interface Operation {
+
+    Class< ? > typeSystem();
+
+    Class<? extends Node> baseClass() default Node.class;
+
+    String[] values() default {};
+
+    String[] shortCircuitValues() default {};
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ShortCircuit.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface ShortCircuit {
+
+    String value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Specialization.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface Specialization {
+
+    int DEFAULT_ORDER = -1;
+
+    int order() default DEFAULT_ORDER;
+
+    SpecializationThrows[] exceptions() default {};
+
+    SpecializationGuard[] guards() default {};
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationGuard.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+/**
+ * Specifies the use of a guard for a specialization.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface SpecializationGuard {
+
+    /**
+     * Specifies the name of the guard method annotated by {@link GuardCheck} specified as method in the
+     * {@link TypeSystem} or {@link Operation} class.
+     */
+    String methodName();
+
+    /**
+     * Determines if a guard check is invoked on specialization. Defaults to true.
+     */
+    boolean onSpecialization() default true;
+
+    /**
+     * Determines if a guard check is invoked on execution. Defaults to true.
+     */
+    boolean onExecution() default true;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationListener.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface SpecializationListener {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationThrows.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface SpecializationThrows {
+
+    Class< ? extends Throwable> javaClass();
+
+    String transitionTo();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCast.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+
+/**
+ *
+ *
+ *
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface TypeCast {
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCheck.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+/**
+ * <p>
+ * Provides a way to define a custom type check for a defined type. The name of the annotated method must fit to the
+ * pattern is${typeName} (eg. isInteger), where ${typeName} must be a valid type defined in the parent
+ * {@link TypeSystem}. The annotated method must have exactly one argument where the type of the argument is the generic
+ * type {@link Object} or a more specific one from the {@link TypeSystem}. You can define multiple overloaded
+ * {@link TypeCheck} methods for the same type. This can be used to reduce the boxing overhead in type conversions.
+ * </p>
+ *
+ * <p>
+ * By default the system generates type checks for all types in the parent {@link TypeSystem} which look like the
+ * follows:
+ *
+ * <pre>
+ * &#064;TypeCheck
+ * boolean is${typeName}(Object value) {
+ *         return value instanceof ${typeName};
+ * }
+ * </pre>
+ *
+ * </p>
+ *
+ * <b>Example:</b>
+ * <p>
+ * A type check for BigInteger with one overloaded optimized variant to reduce boxing.
+ * </p>
+ *
+ * <pre>
+ *
+ *
+ * &#064;TypeSystem(types = {int.class, BigInteger.class, String.class}, nodeBaseClass = TypedNode.class)
+ * public abstract class Types {
+ *
+ *     &#064;TypeCheck
+ *     public boolean isBigInteger(Object value) {
+ *         return value instanceof Integer || value instanceof BigInteger;
+ *     }
+ *
+ *     &#064;TypeCheck
+ *     public boolean isBigInteger(int value) {
+ *         return true;
+ *     }
+ *
+ * }
+ * </pre>
+ *
+ *
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface TypeCheck {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.codegen;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <p>
+ * Annotates a type system class that represents type information for a node. Generates code for converting and managing
+ * types. Methods contained in the type system may be annotated with {@link TypeCast}, {@link TypeCheck} or
+ * {@link GuardCheck}. These methods alter the default behavior of the type system.
+ * </p>
+ *
+ *
+ * <b>Example:</b>
+ * <p>
+ * Shows a <code>@TypeSystem</code> definition with three types. In this example BigIntegers can be also treated as
+ * integers if their bit width is less than 32.
+ * </p>
+ *
+ * <pre>
+ *
+ * &#064;TypeSystem(types = {int.class, BigInteger.class, String.class}, nodeBaseClass = TypedNode.class)
+ * public abstract class Types {
+ *
+ *     &#064;TypeCheck
+ *     public boolean isInteger(Object value) {
+ *         return value instanceof Integer || (value instanceof BigInteger &amp;&amp; ((BigInteger) value).bitLength() &lt; Integer.SIZE);
+ *     }
+ *
+ *     &#064;TypeCast
+ *     public int asInteger(Object value) {
+ *         if (value instanceof Integer) {
+ *             return (int) value;
+ *         } else {
+ *             return ((BigInteger) value).intValue();
+ *         }
+ *     }
+ * }
+ * </pre>
+ *
+ * @see TypeCast
+ * @see TypeCheck
+ * @see GuardCheck
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+public @interface TypeSystem {
+
+    /**
+     * Sets the types contained by this type system. The order of types also determines the order of specialization.
+     */
+    Class[] types();
+
+    /**
+     * Specifies whether the node base class has an executeVoid method or not. Operations derived from this type system
+     * will automatically implement executeVoid for all generated nodes. Defaults to false.
+     */
+    boolean hasVoid() default false;
+
+    /**
+     * Specifies the node base class used for generated code that uses this type system. The node base class must extend
+     * {@link Node} and provide a public non-final method <code>${type} execute${typeName}(VirtualFrame)</code> for all
+     * types specified in the types attribute.
+     */
+    Class< ? extends Node> nodeBaseClass();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/META-INF/services/javax.annotation.processing.Processor	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,1 @@
+com.oracle.truffle.codegen.processor.TruffleProcessor
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor;
+
+import java.lang.annotation.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.codegen.processor.template.*;
+
+/**
+ * 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(ProcessorContext c) {
+        this.context = c;
+        this.processingEnv = c.getEnvironment();
+        this.log = c.getLog();
+    }
+
+    public final M parse(RoundEnvironment env, Element element) {
+        this.roundEnv = env;
+        try {
+            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType());
+            if (!context.getTruffleTypes().verify(context, element, mirror)) {
+                return null;
+            }
+            return parse(element, mirror);
+        } finally {
+            this.roundEnv = null;
+        }
+    }
+
+    protected abstract M parse(Element element, AnnotationMirror mirror);
+
+    public abstract Class< ? extends Annotation> getAnnotationType();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AnnotationProcessor.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor;
+
+import java.io.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.tools.*;
+
+import com.oracle.truffle.codegen.processor.ast.*;
+import com.oracle.truffle.codegen.processor.codewriter.*;
+import com.oracle.truffle.codegen.processor.compiler.*;
+import com.oracle.truffle.codegen.processor.template.*;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+class AnnotationProcessor<M extends Template> {
+
+    private final AbstractParser<M> parser;
+    private final CompilationUnitFactory<M> factory;
+    private final ProcessorContext context;
+
+    private final Set<String> processedElements = new HashSet<>();
+
+    public AnnotationProcessor(ProcessorContext context, AbstractParser<M> parser, CompilationUnitFactory<M> factory) {
+        this.context = context;
+        this.parser = parser;
+        this.factory = factory;
+    }
+
+    public AbstractParser<M> getParser() {
+        return parser;
+    }
+
+    public ProcessorContext getContext() {
+        return context;
+    }
+
+    @SuppressWarnings({"unchecked"})
+    public void process(RoundEnvironment env, 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);
+            if (processedElements.contains(qualifiedName)) {
+                return;
+            }
+            processedElements.add(qualifiedName);
+        }
+
+        TypeElement type = (TypeElement) element;
+
+        M model = (M) context.getTemplate(type.asType(), false);
+        boolean firstRun = !context.containsTemplate(type);
+
+        if (firstRun || !callback) {
+            context.registerTemplate(type, null);
+            model = parser.parse(env, element);
+            context.registerTemplate(type, model);
+
+            if (model != null) {
+                CodeCompilationUnit unit = (CodeCompilationUnit) factory.process(model);
+                unit.setGeneratorAnnotationMirror(model.getTemplateTypeAnnotation());
+                unit.setGeneratorElement(model.getTemplateType());
+
+                DeclaredType overrideType = (DeclaredType) context.getType(Override.class);
+                DeclaredType unusedType = (DeclaredType) context.getType(SuppressWarnings.class);
+                unit.accept(new GenerateOverrideVisitor(overrideType), null);
+                unit.accept(new FixWarningsVisitor(context, unusedType, overrideType), null);
+
+                if (!callback) {
+                    unit.accept(new CodeWriter(context.getEnvironment(), element), null);
+                }
+            }
+        }
+    }
+
+    private static class CodeWriter extends AbstractCodeWriter {
+
+        private final Element orignalElement;
+        private final ProcessingEnvironment env;
+
+        public CodeWriter(ProcessingEnvironment env, Element originalElement) {
+            this.env = env;
+            this.orignalElement = originalElement;
+        }
+
+        @Override
+        protected Writer createWriter(CodeTypeElement clazz) throws IOException {
+            JavaFileObject jfo = env.getFiler().createSourceFile(clazz.getQualifiedName(), orignalElement);
+            return jfo.openWriter();
+        }
+
+        @Override
+        protected void writeHeader() {
+            if (env == null) {
+                return;
+            }
+            String comment = CompilerFactory.getCompiler(orignalElement).getHeaderComment(env, orignalElement);
+            if (comment != null) {
+                writeLn(comment);
+            }
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.codegen.processor;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.truffle.codegen.processor.ast.*;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+public class Log {
+
+    private final ProcessingEnvironment processingEnv;
+
+    public Log(ProcessingEnvironment env) {
+        this.processingEnv = env;
+    }
+
+    public void warning(Element element, String format, Object ... args) {
+        message(Kind.WARNING, element, null, null, format, args);
+    }
+
+    public void warning(Element element, AnnotationMirror mirror, String format, Object ... args) {
+        message(Kind.WARNING, element, mirror, null, format, args);
+    }
+
+    public void error(Element element, String format, Object... args) {
+        message(Kind.ERROR, element, null, null, format, args);
+    }
+
+    public void error(Element element, AnnotationMirror mirror, String format, Object... args) {
+        message(Kind.ERROR, element, mirror, null, format, args);
+    }
+
+    public void error(Element element, AnnotationMirror mirror, AnnotationValue value, String format, Object... args) {
+        message(Kind.ERROR, element, mirror, value, format, args);
+    }
+
+    public void message(Kind kind, Element element, AnnotationMirror mirror, AnnotationValue value, String format, Object... args) {
+        AnnotationMirror usedMirror = mirror;
+        Element usedElement = element;
+        AnnotationValue usedValue = value;
+        String message = String.format(format, args);
+
+        if (element instanceof GeneratedElement) {
+            usedMirror = ((GeneratedElement) element).getGeneratorAnnotationMirror();
+            usedElement = ((GeneratedElement) element).getGeneratorElement();
+            usedValue = null;
+            if (usedElement != null) {
+                message = String.format("Element %s: %s", element, message);
+            }
+        }
+        processingEnv.getMessager().printMessage(kind, message, usedElement, usedMirror, usedValue);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ProcessorContext.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor;
+
+import static com.oracle.truffle.codegen.processor.Utils.*;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.ast.CodeTypeMirror.ArrayCodeTypeMirror;
+import com.oracle.truffle.codegen.processor.template.*;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+public class ProcessorContext {
+
+    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) {
+        this.environment = env;
+        this.callback = callback;
+        this.log = new Log(environment);
+        this.truffleTypes = new TruffleTypes(this);
+    }
+
+    public TruffleTypes getTruffleTypes() {
+        return truffleTypes;
+    }
+
+    public Log getLog() {
+        return log;
+    }
+
+    public ProcessingEnvironment getEnvironment() {
+        return environment;
+    }
+
+    public boolean containsTemplate(TypeElement element) {
+        return models.containsKey(Utils.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);
+    }
+
+    public Template getTemplate(TypeMirror templateTypeMirror, boolean invokeCallback) {
+        String qualifiedName = Utils.getQualifiedName(templateTypeMirror);
+        Template model = models.get(qualifiedName);
+        if (model == null && invokeCallback) {
+            callback.callback(Utils.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()) {
+            if (element == boolean.class) {
+                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.BOOLEAN);
+            } else if (element == byte.class) {
+                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.BYTE);
+            } else if (element == short.class) {
+                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.SHORT);
+            } else if (element == char.class) {
+                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.CHAR);
+            } else if (element == int.class) {
+                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.INT);
+            } else if (element == long.class) {
+                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.LONG);
+            } else if (element == float.class) {
+                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.FLOAT);
+            } else if (element == double.class) {
+                mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.DOUBLE);
+            } else if (element == void.class) {
+                mirror = environment.getTypeUtils().getNoType(TypeKind.VOID);
+            } else {
+                assert false;
+                return null;
+            }
+        } else {
+            TypeElement typeElement = environment.getElementUtils().getTypeElement(element.getCanonicalName());
+            mirror = typeElement.asType();
+        }
+        return mirror;
+    }
+
+    public interface ProcessCallback {
+
+        void callback(TypeElement template);
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.codegen.processor;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.codegen.processor.ProcessorContext.ProcessCallback;
+import com.oracle.truffle.codegen.processor.operation.*;
+import com.oracle.truffle.codegen.processor.typesystem.*;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+//@SupportedAnnotationTypes({"com.oracle.truffle.codegen.Operation", "com.oracle.truffle.codegen.TypeLattice"})
+@SupportedSourceVersion(SourceVersion.RELEASE_7)
+public class TruffleProcessor extends AbstractProcessor implements ProcessCallback {
+
+    private ProcessorContext context;
+    private List<AnnotationProcessor< ? >> generators;
+
+    private RoundEnvironment round;
+
+    @Override
+    public boolean process(Set< ? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        if (!roundEnv.processingOver()) {
+            processImpl(roundEnv);
+        }
+        return false;
+    }
+
+    @SuppressWarnings("unchecked")
+    private void processImpl(RoundEnvironment env) {
+        this.round = env;
+        // TODO run verifications that other annotations are not processed out of scope of the operation or typelattice.
+        try {
+            for (AnnotationProcessor generator : getGenerators()) {
+                for (Element e : env.getElementsAnnotatedWith(generator.getParser().getAnnotationType())) {
+                    processElement(env, generator, e, false);
+                }
+            }
+        } finally {
+            this.round = null;
+        }
+    }
+
+    private static void processElement(RoundEnvironment env, AnnotationProcessor generator, Element e, boolean callback) {
+        try {
+            generator.process(env, e, callback);
+        } catch (Throwable e1) {
+            handleThrowable(generator, e1, e);
+        }
+    }
+
+    private static void handleThrowable(AnnotationProcessor generator, Throwable t, Element e) {
+        String message = "Uncaught error in " + generator.getClass().getSimpleName() + " while processing " + e;
+        generator.getContext().getLog().error(e, message + ": " + Utils.printException(t));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void callback(TypeElement template) {
+        for (AnnotationProcessor generator : generators) {
+            Annotation annotation = template.getAnnotation(generator.getParser().getAnnotationType());
+            if (annotation != null) {
+                processElement(round, generator, template, true);
+            }
+        }
+    }
+
+    @Override
+    public Set<String> getSupportedAnnotationTypes() {
+        Set<String> annotations = new HashSet<>();
+        for (AnnotationProcessor< ? > generator : getGenerators()) {
+            annotations.add(generator.getParser().getAnnotationType().getCanonicalName());
+        }
+        return annotations;
+    }
+
+    private List<AnnotationProcessor< ? >> getGenerators() {
+        if (generators == null && processingEnv != null) {
+            generators = new ArrayList<>();
+            generators.add(new AnnotationProcessor<>(getContext(), new TypeSystemParser(getContext()), new TypeSystemCodeGenerator(getContext())));
+            generators.add(new AnnotationProcessor<>(getContext(), new OperationParser(getContext()), new OperationCodeGenerator(getContext())));
+        }
+        return generators;
+    }
+
+    private ProcessorContext getContext() {
+        if (context == null) {
+            context = new ProcessorContext(processingEnv, this);
+        }
+        return context;
+    }
+
+    @Override
+    public synchronized void init(ProcessingEnvironment env) {
+        this.processingEnv = env;
+        super.init(env);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.Node.Child;
+import com.oracle.truffle.api.nodes.Node.Children;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+public final class TruffleTypes {
+
+    private final TypeMirror node;
+    private final TypeMirror nodeArray;
+    private final TypeMirror unexpectedValueException;
+    private final TypeMirror frame;
+    private final TypeMirror stableAnnotation;
+    private final TypeMirror contentStableAnnotation;
+    private final TypeMirror typeConversion;
+
+    private final List<String> errors = new ArrayList<>();
+
+    public TruffleTypes(ProcessorContext context) {
+        node = getRequired(context, Node.class);
+        nodeArray = context.getEnvironment().getTypeUtils().getArrayType(node);
+        unexpectedValueException = getRequired(context, UnexpectedResultException.class);
+        frame = getRequired(context, VirtualFrame.class);
+        stableAnnotation = getRequired(context, Child.class);
+        contentStableAnnotation = getRequired(context, Children.class);
+        typeConversion = getRequired(context, TypeConversion.class);
+    }
+
+    public boolean verify(ProcessorContext context, Element element, AnnotationMirror mirror) {
+        if (errors.isEmpty()) {
+            return true;
+        }
+
+        for (String error : errors) {
+            context.getLog().error(element, mirror, error);
+        }
+
+        return false;
+    }
+
+    private TypeMirror getRequired(ProcessorContext context, Class clazz) {
+        TypeMirror type = context.getType(clazz);
+        if (type == null) {
+            errors.add(String.format("Could not find required type: %s", clazz.getSimpleName()));
+        }
+        return type;
+    }
+
+    public TypeMirror getTypeConversion() {
+        return typeConversion;
+    }
+
+    public TypeMirror getNode() {
+        return node;
+    }
+
+    public TypeMirror getNodeArray() {
+        return nodeArray;
+    }
+
+    public TypeMirror getFrame() {
+        return frame;
+    }
+
+    public TypeMirror getUnexpectedValueException() {
+        return unexpectedValueException;
+    }
+
+    public TypeMirror getStableAnnotation() {
+        return stableAnnotation;
+    }
+
+    public TypeMirror getContentStableAnnotation() {
+        return contentStableAnnotation;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,551 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor;
+
+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.codegen.processor.ast.*;
+import com.oracle.truffle.codegen.processor.compiler.*;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+public class Utils {
+
+    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 List<AnnotationMirror> collectAnnotations(
+                    ProcessorContext context,
+                    AnnotationMirror markerAnnotation, String elementName, Element element,
+                    Class< ? extends Annotation> annotationClass) {
+        List<AnnotationMirror> result = Utils.getAnnotationValueList(markerAnnotation, elementName);
+        AnnotationMirror explicit = Utils.findAnnotationMirror(context.getEnvironment(), element, annotationClass);
+        if (explicit != null) {
+            result.add(explicit);
+        }
+
+        for (AnnotationMirror mirror : result) {
+            assert Utils.typeEquals(mirror.getAnnotationType(), context.getType(annotationClass));
+        }
+        return result;
+    }
+
+    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);
+        }
+    }
+
+    /**
+     * True if t1 is assignable to t2.
+     */
+    public static boolean isAssignable(TypeMirror t1, TypeMirror t2) {
+        if (typeEquals(t1, t2)) {
+            return true;
+        }
+        if (isPrimitive(t1) || isPrimitive(t2)) {
+            // non-equal primitive types
+            return false;
+        }
+        if (t1 instanceof ArrayType && t2 instanceof ArrayType) {
+            return isAssignable(((ArrayType) t1).getComponentType(), ((ArrayType) t2).getComponentType());
+        }
+
+        TypeElement e1 = fromTypeMirror(t1);
+        TypeElement e2 = fromTypeMirror(t2);
+        if (e1 == null || e2 == null) {
+            return false;
+        }
+
+        List<TypeElement> superTypes = getSuperTypes(e1);
+        for (TypeElement superType : superTypes) {
+            if (typeEquals(superType.asType(), t2)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static Set<Modifier> modifiers(Modifier... modifier) {
+        return new LinkedHashSet<>(Arrays.asList(modifier));
+    }
+
+    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 getGenericName(fromTypeMirror(mirror));
+            case ARRAY:
+                return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]";
+            case VOID:
+                return "void";
+            case TYPEVAR:
+                return ((TypeParameterElement) ((TypeVariable) mirror).asElement()).getSimpleName().toString();
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
+        }
+    }
+
+
+    private static String getGenericName(TypeElement element) {
+        String simpleName = element.getSimpleName().toString();
+
+        if (element.getTypeParameters().size() == 0) {
+            return simpleName;
+        }
+
+        StringBuilder b = new StringBuilder(simpleName);
+        b.append("<");
+        if (element.getTypeParameters().size() > 0) {
+            for (int i = 0; i < element.getTypeParameters().size(); i++) {
+                b.append("?");
+                if (i < element.getTypeParameters().size() - 1) {
+                    b.append(", ");
+                }
+            }
+        }
+        b.append(">");
+        return b.toString();
+    }
+
+    public static String getQualifiedName(TypeElement element) {
+        return element.getQualifiedName().toString();
+    }
+
+    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);
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror);
+        }
+    }
+
+    public static boolean isVoid(TypeMirror mirror) {
+        return mirror.getKind() == TypeKind.VOID;
+    }
+
+    public static boolean isPrimitive(TypeMirror mirror) {
+        return 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 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 TypeElement findEnclosingType(Element element) {
+        Element enclosing = element.getEnclosingElement();
+        while (enclosing.getKind() != ElementKind.CLASS && enclosing.getKind() != ElementKind.ENUM && enclosing.getKind() != ElementKind.INTERFACE) {
+            enclosing = element.getEnclosingElement();
+        }
+
+        return (TypeElement) enclosing;
+    }
+
+    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(AnnotationMirror mirror, String name) {
+        List<T> result = new ArrayList<>();
+        List< ? extends AnnotationValue> values = (List< ? extends AnnotationValue>) getAnnotationValue(mirror, name).getValue();
+        for (AnnotationValue value : values) {
+            result.add((T) value.getValue());
+        }
+        return result;
+    }
+
+    public static TypeMirror getAnnotationValueType(AnnotationMirror mirror, String name) {
+        return (TypeMirror) getAnnotationValue(mirror, name).getValue();
+    }
+
+    public static TypeMirror getAnnotationValueTypeMirror(AnnotationMirror mirror, String name) {
+        return (TypeMirror) getAnnotationValue(mirror, name).getValue();
+    }
+
+    public static String getAnnotationValueString(AnnotationMirror mirror, String name) {
+        return (String) getAnnotationValue(mirror, name).getValue();
+    }
+
+    public static int getAnnotationValueInt(AnnotationMirror mirror, String name) {
+        return (int) getAnnotationValue(mirror, name).getValue();
+    }
+
+    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;
+    }
+
+    public static boolean getAnnotationValueBoolean(AnnotationMirror mirror, String name) {
+        return (Boolean) getAnnotationValue(mirror, name).getValue();
+    }
+
+    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.getName());
+        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) {
+        Element searchType = type;
+        while (searchType.getEnclosingElement() != null && searchType.getEnclosingElement().getKind() != ElementKind.PACKAGE) {
+            searchType = type.getEnclosingElement();
+        }
+        return (PackageElement) searchType.getEnclosingElement();
+    }
+
+    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 (!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;
+        }
+        String qualified1 = getQualifiedName(type1);
+        String qualified2 = getQualifiedName(type2);
+        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 supertypes
+        TypeElement exceptionTypeElement = fromTypeMirror(exceptionType);
+        List<TypeElement> superTypes = getSuperTypes(exceptionTypeElement);
+        for (TypeElement typeElement : superTypes) {
+            if (Utils.containsType(thrownTypes, typeElement.asType())) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    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 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;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/ExtensionContext.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.api;
+
+import javax.annotation.processing.*;
+
+import com.oracle.truffle.codegen.processor.api.element.*;
+
+
+public interface ExtensionContext {
+
+    ProcessingEnvironment getProcessingEnvironment();
+
+    RoundEnvironment getRoundEnvironment();
+
+    WritableElementFactory getElementFactory();
+
+    void addGeneratedElement(WritableElement element);
+
+    void removeGeneratedElement(WritableElement element);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/ExtensionProcessor.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.api;
+
+import javax.lang.model.element.*;
+
+
+public interface ExtensionProcessor {
+
+    void process(ExtensionContext context, AnnotationMirror mirror, Element element);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableAnnotationMirror.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.api.element;
+
+import javax.lang.model.element.*;
+
+public interface WritableAnnotationMirror extends AnnotationMirror {
+
+    void setElementValue(ExecutableElement valueName, AnnotationValue value);
+
+    AnnotationValue getElementValue(ExecutableElement valueName);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableElement.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.api.element;
+
+import javax.lang.model.element.*;
+
+
+public interface WritableElement extends Element {
+
+    void addAnnotationMirror(AnnotationMirror annotationMirror);
+
+    void removeAnnotationMirror(AnnotationMirror annotationMirror);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableElementFactory.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.api.element;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+
+public interface WritableElementFactory {
+
+    WritableExecutableElement cloneExecutableElement(ExecutableElement method);
+    WritableVariableElement cloneVariableElement(VariableElement parameter);
+    WritableAnnotationMirror cloneAnnotationMirror(AnnotationMirror mirror);
+
+    WritableVariableElement createParameter(TypeMirror type, String simpleName);
+    WritableExecutableElement createExecutableElement(TypeMirror returnType, String methodName);
+    WritableAnnotationMirror createAnnotationMirror(DeclaredType annotationClass);
+
+    Name createName(String name);
+    AnnotationValue createAnnotationValue(Object value);
+    TypeMirror createTypeMirror(Class<?> javaClass);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableExecutableElement.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.api.element;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public interface WritableExecutableElement extends ExecutableElement, WritableElement {
+
+    void setReturnType(TypeMirror type);
+    void setDefaultValue(AnnotationValue defaultValue);
+
+    void addParameter(VariableElement parameter);
+    void removeParamter(VariableElement parameter);
+
+    void addThrownType(TypeMirror thrownType);
+    void removeThrownType(TypeMirror thrownType);
+
+    void setSimpleName(Name name);
+    void setVarArgs(boolean varargs);
+
+    void setBody(String body);
+    String getBody();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableVariableElement.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.api.element;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public interface WritableVariableElement extends VariableElement, WritableElement {
+
+    void setSimpleName(Name name);
+    void setType(TypeMirror type);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationMirror.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.ast;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.codegen.processor.api.element.*;
+
+public class CodeAnnotationMirror implements WritableAnnotationMirror {
+
+    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;
+    }
+
+    @Override
+    public AnnotationValue getElementValue(ExecutableElement method) {
+        return values.get(method);
+    }
+
+    @Override
+    public void setElementValue(ExecutableElement method, AnnotationValue value) {
+        values.put(method, value);
+    }
+
+    public ExecutableElement findExecutableElement(String name) {
+        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(annotationType.asElement().getEnclosedElements());
+        for (ExecutableElement executableElement : elements) {
+            if (executableElement.getSimpleName().toString().equals(name)) {
+                return executableElement;
+            }
+        }
+        return null;
+    }
+
+    public static CodeAnnotationMirror clone(AnnotationMirror mirror) {
+        CodeAnnotationMirror copy = new CodeAnnotationMirror(mirror.getAnnotationType());
+        for (ExecutableElement key : mirror.getElementValues().keySet()) {
+            copy.setElementValue(key, mirror.getElementValues().get(key));
+        }
+        return copy;
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationValue.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.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);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeCompilationUnit.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.codegen.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 (TypeElement type : getEnclosedElements()) {
+            type.accept(v, p);
+        }
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.ast;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.codegen.processor.api.element.*;
+import com.oracle.truffle.codegen.processor.codewriter.*;
+
+public abstract class CodeElement<E extends Element> implements WritableElement, 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<>();
+    }
+
+
+    @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 CodeElement(Set<Modifier> modifiers) {
+        this.modifiers = new LinkedHashSet<>(modifiers);
+    }
+
+    public E add(E element) {
+        if (element == null) {
+            throw new NullPointerException();
+        }
+        getEnclosedElements().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;
+    }
+
+    @Override
+    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void addAnnotationMirror(AnnotationMirror annotationMirror) {
+        getAnnotationMirrors().add(annotationMirror);
+    }
+
+    public void removeAnnotationMirror(AnnotationMirror annotationMirror) {
+        getAnnotationMirrors().remove(annotationMirror);
+    }
+
+    void setEnclosingElement(Element parent) {
+        if (this.enclosingElement != null && parent != null) {
+            throw new IllegalStateException("Element already added to " + 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());
+        }
+
+    }
+
+
+    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.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElementScanner.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.codegen.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) {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.ast;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.api.element.*;
+
+public class CodeExecutableElement extends CodeElement<Element> implements WritableExecutableElement {
+
+    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);
+        }
+    }
+
+    @Override
+    public List<TypeMirror> getThrownTypes() {
+        return throwables;
+    }
+
+    @Override
+    public TypeMirror asType() {
+        return returnType;
+    }
+
+    @Override
+    public ElementKind getKind() {
+        return ElementKind.METHOD;
+    }
+
+    @Override
+    public List< ? extends TypeParameterElement> getTypeParameters() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public void setVarArgs(boolean varargs) {
+        this.varArgs = varargs;
+    }
+
+    @Override
+    public boolean isVarArgs() {
+        return varArgs;
+    }
+
+    @Override
+    public void setDefaultValue(AnnotationValue defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+
+    @Override
+    public AnnotationValue getDefaultValue() {
+        return defaultValue;
+    }
+
+    @Override
+    public Name getSimpleName() {
+        return name;
+    }
+
+    public CodeTreeBuilder createBuilder() {
+        CodeTreeBuilder builder = new CodeTreeBuilder();
+        this.bodyTree = builder.getTree();
+        this.bodyTree.setEnclosingElement(this);
+        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;
+    }
+
+    @Override
+    public void setReturnType(TypeMirror type) {
+        returnType = type;
+    }
+
+    @Override
+    public void addParameter(VariableElement parameter) {
+        parameters.add(parameter);
+    }
+
+    @Override
+    public void removeParamter(VariableElement parameter) {
+        parameters.remove(parameter);
+    }
+
+    @Override
+    public void addThrownType(TypeMirror thrownType) {
+        throwables.add(thrownType);
+    }
+
+    @Override
+    public void removeThrownType(TypeMirror thrownType) {
+        throwables.remove(thrownType);
+    }
+
+    @Override
+    public void setSimpleName(Name name) {
+        this.name = name;
+    }
+
+    @Override
+    public void setBody(String body) {
+        this.body = body;
+    }
+
+    @Override
+    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(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(var);
+        }
+        for (Element element : method.getEnclosedElements()) {
+            copy.add(element);
+        }
+        copy.setBody(Utils.getMethodBody(env, method));
+        copy.getModifiers().addAll(method.getModifiers());
+        return copy;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeImport.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.codegen.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;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeNames.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.codegen.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;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTree.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.ast;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class CodeTree extends CodeElement<CodeTree> {
+
+    private final CodeTreeKind kind;
+
+    private final TypeMirror type;
+    private final String string;
+
+    public 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);
+    }
+
+    @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.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,705 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.ast;
+
+import static com.oracle.truffle.codegen.processor.ast.CodeTreeKind.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.*;
+
+public class CodeTreeBuilder {
+
+    private BuilderCodeTree currentElement;
+    private final BuilderCodeTree root;
+
+    public CodeTreeBuilder() {
+        this.root = new BuilderCodeTree(GROUP, null, null);
+        this.currentElement = root;
+    }
+
+    public CodeTreeBuilder(CodeTree tree) {
+        this.root = (BuilderCodeTree) tree;
+        this.currentElement = root;
+    }
+
+    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();
+    }
+
+    public static CodeTree singleString(String s) {
+        return new CodeTreeBuilder().string(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) {
+            currentElement.add(tree);
+        }
+        switch (tree.getCodeKind()) {
+            case COMMA_GROUP:
+            case GROUP:
+            case INDENT:
+                currentElement = tree;
+                break;
+        }
+        return this;
+    }
+
+    private void clearLast(CodeTreeKind kind) {
+        clearLastRec(kind, currentElement.getEnclosedElements());
+    }
+
+    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(null, callSite);
+    }
+
+    public CodeTreeBuilder startCall(String receiver, String callSite) {
+        if (receiver == null) {
+            return startGroup().string(callSite).startParanthesesCommaGroup().endAfter();
+        } else {
+            return startGroup().string(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.findEnclosingType(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;
+    }
+
+    public CodeTreeBuilder startParantheses() {
+        startGroup();
+        string("(").startGroup();
+        registerCallBack(new EndCallback() {
+            @Override
+            public void beforeEnd() {
+            }
+            @Override
+            public void afterEnd() {
+                string(")");
+            }
+        });
+        endAfter();
+        return this;
+    }
+
+    public CodeTreeBuilder startDoubleQuote() {
+        startGroup().string("\"");
+        registerCallBack(new EndCallback() {
+            @Override
+            public void beforeEnd() {
+            }
+            @Override
+            public void afterEnd() {
+                string("\"");
+            }
+        });
+        return this;
+    }
+
+    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) {
+        return push((BuilderCodeTree) treeToAdd).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 startIf() {
+        return startGroup().string("if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
+    }
+
+    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())) {
+            startStatement();
+            return this;
+        } else {
+            return startStatement().string("return ");
+        }
+    }
+
+    public CodeTreeBuilder startAssert() {
+        return startStatement().string("assert ");
+    }
+
+    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() {
+        BuilderCodeTree tree = currentElement;
+        EndCallback callback = tree.getAtEndListener();
+        if (callback != null) {
+            callback.beforeEnd();
+            toParent();
+            callback.afterEnd();
+        } else {
+            toParent();
+        }
+        return this;
+    }
+
+    private void toParent() {
+        Element parent = currentElement.getEnclosingElement();
+        if (currentElement != root) {
+            this.currentElement = (BuilderCodeTree) parent;
+        } 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 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(TypeMirror type, String name) {
+        return declaration(type, name, (CodeTree) null);
+    }
+
+    public CodeTreeBuilder create() {
+        return new CodeTreeBuilder();
+    }
+
+    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(TypeMirror type, CodeTree content) {
+        if (Utils.isVoid(type)) {
+            tree(content);
+            return this;
+        } else if (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");
+    }
+
+    private ExecutableElement findMethod() {
+        Element element = currentElement;
+        while (element != null && (element.getKind() != ElementKind.METHOD)) {
+            element = element.getEnclosingElement();
+        }
+        return element != null ? (ExecutableElement) element : null;
+    }
+
+    public CodeTreeBuilder returnTrue() {
+        return startReturn().string("true").end();
+    }
+
+    public CodeTreeBuilder instanceOf(String var, TypeMirror type) {
+        string(var);
+        TypeElement element = Utils.fromTypeMirror(type);
+        if (element == null) {
+            throw new IllegalArgumentException("Cannot call instanceof for a non supported type: " + type.getKind());
+        }
+
+        string(" instanceof ").type(type);
+        return this;
+    }
+
+    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 null_() {
+        return string("null");
+    }
+
+    private static class BuilderCodeTree extends CodeTree {
+
+        private EndCallback atEndListener;
+
+        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("    ");
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeKind.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.ast;
+
+public enum CodeTreeKind {
+    STATIC_FIELD_REFERENCE, STATIC_METHOD_REFERENCE, GROUP, COMMA_GROUP, INDENT, STRING, NEW_LINE, TYPE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeElement.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.codegen.processor.ast;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.codegen.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;
+    }
+
+    public CodeVariableElement getField(String name) {
+        for (VariableElement field : ElementFilter.fieldsIn(getEnclosedElements())) {
+            if (field.getSimpleName().toString().equals(name)) {
+                return (CodeVariableElement) field;
+            }
+        }
+        return null;
+    }
+
+    private Name createQualifiedName() {
+        TypeElement enclosingType = getEnclosingClass();
+        if (enclosingType == null) {
+            return CodeNames.of(packageName + "." + simpleName);
+        } else {
+            return CodeNames.of(enclosingType.getQualifiedName() + "." + simpleName);
+        }
+    }
+
+    @Override
+    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 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.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.ast;
+
+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 CodeTypeElement clazz;
+
+        public DeclaredCodeTypeMirror(CodeTypeElement clazz) {
+            super(TypeKind.DECLARED);
+            this.clazz = clazz;
+        }
+
+        @Override
+        public Element asElement() {
+            return clazz;
+        }
+
+        @Override
+        public TypeMirror getEnclosingType() {
+            return clazz.getEnclosingElement().asType();
+        }
+
+        @Override
+        public List< ? extends TypeMirror> getTypeArguments() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public String toString() {
+            return clazz.getQualifiedName().toString();
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeVariableElement.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.ast;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.api.element.*;
+
+public final class CodeVariableElement extends CodeElement<Element> implements WritableVariableElement {
+
+    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();
+        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();
+    }
+
+    @Override
+    public void setSimpleName(Name name) {
+        this.name = name;
+    }
+
+    public void setName(String name) {
+        this.name = CodeNames.of(name);
+    }
+
+    @Override
+    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.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/GeneratedElement.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.codegen.processor.ast;
+
+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.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,608 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.codewriter;
+
+import static com.oracle.truffle.codegen.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.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.ast.*;
+
+public abstract class AbstractCodeWriter extends CodeElementScanner<Void, Void> {
+
+    protected Writer writer;
+    private int indent;
+    private boolean newLine;
+
+    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 = 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 void writeClassImpl(CodeTypeElement e) {
+        for (AnnotationMirror annotation : e.getAnnotationMirrors()) {
+            visitAnnotation(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(typeSimpleName(e.getSuperclass()));
+        }
+        if (e.getImplements().size() > 0) {
+            write(" implements ");
+            for (int i = 0; i < e.getImplements().size(); i++) {
+                write(typeSimpleName(e.getImplements().get(i)));
+                if (i < e.getImplements().size() - 1) {
+                    write(", ");
+                }
+            }
+        }
+
+        write(" {").writeLn();
+        writeEmptyLn();
+        indent();
+
+        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 : 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();
+        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(annotation);
+            writeLn();
+        }
+
+        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) {
+                if (init != null) {
+                    write("(");
+                    init.acceptCodeElementScanner(this, p);
+                    write(")");
+                }
+            }
+        } else {
+            writeModifiers(f.getModifiers());
+            write(typeSimpleName(f.asType()));
+            write(" ");
+            write(f.getSimpleName());
+            if (init != null) {
+                write(" = ");
+                init.acceptCodeElementScanner(this, p);
+            }
+        }
+        return null;
+    }
+
+    public void visitAnnotation(AnnotationMirror e) {
+        write("@").write(typeSimpleName(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(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(value);
+
+                    if (i < methodsList.size() - 1) {
+                        write(", ");
+                    }
+                }
+            }
+
+            write(")");
+        }
+    }
+
+    public void visitAnnotationValue(AnnotationValue e) {
+        e.accept(new AnnotationValueWriterVisitor(), null);
+    }
+
+    private class AnnotationValueWriterVisitor extends AbstractAnnotationValueVisitor7<Void, Void> {
+        @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(typeSimpleName(t));
+            write(".class");
+            return null;
+        }
+        @Override
+        public Void visitEnumConstant(VariableElement c, Void p) {
+            write(typeSimpleName(c.asType()));
+            write(".");
+            write(c.getSimpleName().toString());
+            return null;
+        }
+        @Override
+        public Void visitAnnotation(AnnotationMirror a, Void p) {
+            AbstractCodeWriter.this.visitAnnotation(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(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 visitParameter(CodeVariableElement e) {
+//        for (CodeAnnotationMirror annotation : e.getAnnotationMirrors()) {
+//            annotation.accept(this);
+//        }
+//        write(typeSimpleName(e.getType()));
+//        write(" ");
+//        write(e.getSimpleName());
+//    }
+
+    @Override
+    public Void visitExecutable(CodeExecutableElement e, Void p) {
+        for (AnnotationMirror annotation : e.getAnnotationMirrors()) {
+            visitAnnotation(annotation);
+            writeLn();
+        }
+
+        writeModifiers(e.getModifiers());
+
+        if (e.getReturnType() != null) {
+            write(typeSimpleName(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(typeSimpleName(throwables.get(i)));
+                if (i < throwables.size() - 1) {
+                    write(", ");
+                }
+            }
+        }
+
+        if (e.getModifiers().contains(Modifier.ABSTRACT)) {
+            writeLn(";");
+        } else if (e.getBodyTree() != null) {
+            writeLn(" {");
+            indent();
+            e.getBodyTree().acceptCodeElementScanner(this, p);
+            dedent();
+            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();
+                for (CodeTree tree : e.getEnclosedElements()) {
+                    tree.acceptCodeElementScanner(this, p);
+                }
+                dedent();
+                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.useStaticFieldImport(e.getType(), e.getString()));
+                } else {
+                    write("null");
+                }
+                break;
+            case STATIC_METHOD_REFERENCE:
+                if (e.getString() != null) {
+                    write(imports.useStaticMethodImport(e.getType(), e.getString()));
+                } else {
+                    write("null");
+                }
+                break;
+            case TYPE:
+                write(imports.useImport(e.getType()));
+                break;
+            default:
+                assert false;
+                return;
+        }
+    }
+
+    private static String typeSimpleName(TypeMirror type) {
+        return Utils.getSimpleName(type);
+    }
+
+    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 static final String LN = "\n";
+
+    protected void indent() {
+        indent++;
+    }
+
+    protected void dedent() {
+        indent--;
+    }
+
+    protected void writeLn() {
+        write(LN);
+        newLine = true;
+    }
+
+    protected void writeLn(String text) {
+        write(text);
+        write(LN);
+        newLine = true;
+    }
+
+    protected void writeEmptyLn() {
+        writeLn();
+    }
+
+    private AbstractCodeWriter write(Name name) {
+        return write(name.toString());
+    }
+
+    private AbstractCodeWriter write(String m) {
+        try {
+            if (newLine && m != LN) {
+                writeIndent();
+                newLine = false;
+            }
+            writer.write(m);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        return this;
+    }
+
+    private void writeIndent() throws IOException {
+        for (int i = 0; i < indent; i++) {
+            writer.write("    ");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/FixWarningsVisitor.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.codewriter;
+
+import static com.oracle.truffle.codegen.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.codegen.processor.*;
+import com.oracle.truffle.codegen.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);
+        if (e.getBodyTree() == null && e.getBody() != null) {
+            computeSymbols(e.getBody());
+        }
+
+        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);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/GenerateOverrideVisitor.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.codewriter;
+
+import static com.oracle.truffle.codegen.processor.Utils.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.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();
+
+            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.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,377 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.codewriter;
+
+import static com.oracle.truffle.codegen.processor.Utils.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.ast.*;
+
+public final class OrganizedImports {
+
+    private final Map<TypeMirror, Integer> importUsage = new HashMap<>();
+    private final Map<TypeMirror, Integer> staticImportUsage = new HashMap<>();
+
+    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);
+
+        OrganizedImports.ReferenceCollector reference = new ReferenceCollector();
+        topLevelClass.accept(reference, null);
+
+        OrganizedImports.ImportResolver resolver = new ImportResolver(reference, organized);
+        topLevelClass.accept(resolver, null);
+        return organized;
+    }
+
+    public String useImport(TypeMirror type) {
+        String simpleName = getSimpleName(type);
+        TypeMirror usedByType = simpleNamesUsed.get(type);
+        if (usedByType == null) {
+            simpleNamesUsed.put(simpleName, type);
+            usedByType = type;
+        } else if (!typeEquals(type, usedByType)) {
+            // we need a qualified name
+            return getQualifiedName(type);
+        }
+
+        // we can use the simple name
+        addUsage(type, importUsage);
+        return simpleName;
+    }
+
+    public String useStaticFieldImport(TypeMirror type, String fieldName) {
+        return useStaticImport(type, fieldName, ambiguousStaticFields, declaredStaticFields);
+    }
+
+    public String useStaticMethodImport(TypeMirror type, String methodName) {
+        return useStaticImport(type, methodName, ambiguousStaticMethods, declaredStaticMethods);
+    }
+
+    private String useStaticImport(TypeMirror type, String name, Set<String> ambiguousSymbols, Set<String> declaredSymbols) {
+        if (ambiguousSymbols.contains(name)) {
+            // ambiguous import
+            return useImport(type) + "." + name;
+        } else if (!declaredSymbols.contains(name)) {
+            // not imported at all
+            return useImport(type) + "." + name;
+        } else {
+            // import declared and not ambiguous
+            addUsage(type, staticImportUsage);
+            return name;
+        }
+    }
+
+    public Set<CodeImport> generateImports() {
+        Set<CodeImport> imports = new HashSet<>();
+
+        imports.addAll(generateImports(topLevelClass, importUsage.keySet()));
+        imports.addAll(generateStaticImports(topLevelClass, staticImportUsage.keySet()));
+
+        return imports;
+    }
+
+    void clearStaticImports() {
+        declaredStaticFields.clear();
+        declaredStaticMethods.clear();
+        ambiguousStaticFields.clear();
+        ambiguousStaticMethods.clear();
+    }
+
+    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 static Set<CodeImport> generateImports(CodeTypeElement e, Set<TypeMirror> toGenerate) {
+        Set<String> autoImportedTypes = new HashSet<>();
+
+        // if type is declared inside a super type of this class -> no import
+        collectSuperTypeImports(e, autoImportedTypes);
+        collectInnerTypeImports(e, autoImportedTypes);
+
+        TreeSet<CodeImport> importObjects = new TreeSet<>();
+        for (TypeMirror importType : toGenerate) {
+            String importTypePackageName = getPackageName(importType);
+            if (importTypePackageName == null) {
+                continue; // no package name -> no import
+            }
+
+            if (importTypePackageName.equals("java.lang")) {
+                continue; // java.lang is automatically imported
+            }
+
+            if (importTypePackageName.equals(getPackageName(e))) {
+                continue; // same package name -> no import
+            }
+
+            String qualifiedName = getQualifiedName(importType);
+
+            if (autoImportedTypes.contains(qualifiedName)) {
+                continue;
+            }
+
+            importObjects.add(new CodeImport(importType, getQualifiedName(importType), false));
+        }
+
+        return importObjects;
+    }
+
+    private static void collectInnerTypeImports(TypeElement e, Set<String> autoImportedTypes) {
+        for (TypeElement innerClass : ElementFilter.typesIn(e.getEnclosedElements())) {
+            collectSuperTypeImports(innerClass, autoImportedTypes);
+            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 static Set<CodeImport> generateStaticImports(CodeTypeElement e, Set<TypeMirror> toGenerate) {
+        Set<String> autoImportedStaticTypes = new HashSet<>();
+
+        // if type is declared inside a super type of this class -> no import
+        autoImportedStaticTypes.add(getQualifiedName(e));
+        autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(e));
+
+        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 static void addUsage(TypeMirror type, Map<TypeMirror, Integer> usageMap) {
+        if (type != null) {
+            Integer value = usageMap.get(type);
+            if (value == null) {
+                usageMap.put(type, 1);
+            } else {
+                usageMap.put(type, value + 1);
+            }
+        }
+    }
+
+    private static class ReferenceCollector extends CodeElementScanner<Void, Void> {
+
+        final Map<TypeMirror, Integer> typeReferences = new HashMap<>();
+        final Map<TypeMirror, Integer> staticTypeReferences = new HashMap<>();
+
+        @Override
+        public void visitTree(CodeTree e, Void p) {
+            if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) {
+                addStaticImport(e.getType());
+            } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) {
+                addStaticImport(e.getType());
+            } else {
+                addImport(e.getType());
+            }
+            super.visitTree(e, p);
+        }
+
+        @Override
+        public Void visitExecutable(CodeExecutableElement e, Void p) {
+            visitAnnotations(e.getAnnotationMirrors());
+            if (e.getReturnType() != null) {
+                addImport(e.getReturnType());
+            }
+            for (TypeMirror type : e.getThrownTypes()) {
+                addImport(type);
+            }
+            return super.visitExecutable(e, p);
+        }
+
+        @Override
+        public Void visitType(CodeTypeElement e, Void p) {
+            visitAnnotations(e.getAnnotationMirrors());
+
+            addImport(e.getSuperclass());
+            for (TypeMirror type : e.getImplements()) {
+                addImport(type);
+            }
+
+            return super.visitType(e, p);
+        }
+
+        @Override
+        public Void visitVariable(VariableElement f, Void p) {
+            visitAnnotations(f.getAnnotationMirrors());
+            addImport(f.asType());
+            return super.visitVariable(f, p);
+        }
+
+        private void visitAnnotations(List<? extends AnnotationMirror> mirrors) {
+            for (AnnotationMirror mirror : mirrors) {
+                visitAnnotation(mirror);
+            }
+        }
+
+        public void visitAnnotation(AnnotationMirror e) {
+            addImport(e.getAnnotationType());
+        }
+
+        @Override
+        public void visitImport(CodeImport e, Void p) {
+        }
+
+        private void addStaticImport(TypeMirror type) {
+            addUsage(type, staticTypeReferences);
+        }
+
+        private void addImport(TypeMirror type) {
+            addUsage(type, typeReferences);
+        }
+
+    }
+
+    private static class ImportResolver extends CodeElementScanner<Void, Void> {
+
+        private final ReferenceCollector collector;
+        private final OrganizedImports organizedImports;
+
+        public ImportResolver(OrganizedImports.ReferenceCollector collector, OrganizedImports organizedImports) {
+            this.collector = collector;
+            this.organizedImports = organizedImports;
+        }
+
+        @Override
+        public Void visitType(CodeTypeElement e, Void p) {
+            if (e.isTopLevelClass()) {
+                organizedImports.clearStaticImports();
+
+                organizedImports.processStaticImports(e);
+                List<TypeElement> types = Utils.getSuperTypes(e);
+                for (TypeElement typeElement : types) {
+                    organizedImports.processStaticImports(typeElement);
+                }
+
+                for (TypeMirror type : collector.staticTypeReferences.keySet()) {
+                    TypeElement element = fromTypeMirror(type);
+                    if (element != null) {
+                        // already processed by supertype
+                        if (types.contains(element)) {
+                            continue;
+                        }
+                        organizedImports.processStaticImports(element);
+                    }
+                }
+
+                for (TypeMirror imp : collector.typeReferences.keySet()) {
+                    organizedImports.useImport(imp);
+                }
+            }
+            return super.visitType(e, p);
+        }
+
+        @Override
+        public void visitTree(CodeTree e, Void p) {
+            if (e.getCodeKind() == CodeTreeKind.TYPE) {
+                organizedImports.useImport(e.getType());
+            } else if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) {
+                organizedImports.useStaticFieldImport(e.getType(), e.getString());
+            } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) {
+                organizedImports.useStaticMethodImport(e.getType(), e.getString());
+            }
+            super.visitTree(e, p);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/AbstractCompiler.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.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 {
+        Field field = o.getClass().getField(fieldName);
+        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.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/Compiler.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.codegen.processor.compiler;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+
+
+public interface Compiler {
+
+    String getMethodBody(ProcessingEnvironment env, ExecutableElement method);
+
+    String getHeaderComment(ProcessingEnvironment env, Element type);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/CompilerFactory.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.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.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JDTCompiler.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.compiler;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.codegen.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;
+        }
+    }
+
+    @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);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JavaCCompiler.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.compiler;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.codegen.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;
+        }
+    }
+
+    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.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionCodeElementFactory.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.ext;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.api.element.*;
+import com.oracle.truffle.codegen.processor.ast.*;
+
+
+final class ExtensionCodeElementFactory implements WritableElementFactory {
+
+    private final ProcessorContext context;
+
+    Element generatorElement;
+    AnnotationMirror generatorAnnotationMirror;
+
+    public ExtensionCodeElementFactory(ProcessorContext context) {
+        this.context = context;
+    }
+
+    @Override
+    public WritableExecutableElement cloneExecutableElement(ExecutableElement method) {
+        return updateGenerators(CodeExecutableElement.clone(context.getEnvironment(), method));
+    }
+
+    @Override
+    public WritableVariableElement cloneVariableElement(VariableElement var) {
+        return updateGenerators(CodeVariableElement.clone(var));
+    }
+
+    @Override
+    public WritableAnnotationMirror cloneAnnotationMirror(AnnotationMirror mirror) {
+        return CodeAnnotationMirror.clone(mirror);
+    }
+
+    @Override
+    public WritableVariableElement createParameter(TypeMirror type, String simpleName) {
+        return updateGenerators(new CodeVariableElement(Utils.modifiers(), type, simpleName));
+    }
+
+    @Override
+    public WritableExecutableElement createExecutableElement(TypeMirror returnType, String methodName) {
+        return updateGenerators(new CodeExecutableElement(returnType, methodName));
+    }
+
+    @Override
+    public TypeMirror createTypeMirror(Class<?> javaClass) {
+        return context.getType(javaClass);
+    }
+
+    @Override
+    public WritableAnnotationMirror createAnnotationMirror(DeclaredType typeMirror) {
+        return new CodeAnnotationMirror(typeMirror);
+    }
+
+    @Override
+    public Name createName(String name) {
+        return CodeNames.of(name);
+    }
+
+    @Override
+    public AnnotationValue createAnnotationValue(Object value) {
+        return new CodeAnnotationValue(value);
+    }
+
+    private <E extends GeneratedElement> E updateGenerators(E element) {
+        element.setGeneratorElement(generatorElement);
+        element.setGeneratorAnnotationMirror(generatorAnnotationMirror);
+        return element;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionContextImpl.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.codegen.processor.ext;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+
+import com.oracle.truffle.codegen.processor.api.*;
+import com.oracle.truffle.codegen.processor.api.element.*;
+
+
+public class ExtensionContextImpl implements ExtensionContext {
+
+    private final ProcessingEnvironment env;
+    private final RoundEnvironment round;
+    private final WritableElementFactory factory;
+
+    private final List<WritableElement> elements = new ArrayList<>();
+
+    public ExtensionContextImpl(ProcessingEnvironment env, RoundEnvironment round, WritableElementFactory factory) {
+        this.env = env;
+        this.round = round;
+        this.factory = factory;
+    }
+
+
+    List<WritableElement> returnElements() {
+        List<WritableElement> returnElements = new ArrayList<>(this.elements);
+        this.elements.clear();
+        return returnElements;
+    }
+
+    @Override
+    public ProcessingEnvironment getProcessingEnvironment() {
+        return env;
+    }
+
+    @Override
+    public RoundEnvironment getRoundEnvironment() {
+        return round;
+    }
+
+    @Override
+    public WritableElementFactory getElementFactory() {
+        return factory;
+    }
+
+    @Override
+    public void addGeneratedElement(WritableElement element) {
+        elements.add(element);
+    }
+
+    @Override
+    public void removeGeneratedElement(WritableElement element) {
+        elements.remove(element);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.codegen.processor.ext;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.api.*;
+import com.oracle.truffle.codegen.processor.api.element.*;
+
+
+public class ExtensionParser {
+
+    private final Map<String, ExtensionProcessor> extensions = new HashMap<>();
+    private final ProcessorContext context;
+    private final ExtensionCodeElementFactory factory;
+    private final ExtensionContextImpl extensionContext;
+
+    public ExtensionParser(ProcessorContext context) {
+        this.context = context;
+        this.factory = new ExtensionCodeElementFactory(context);
+        this.extensionContext = new ExtensionContextImpl(context.getEnvironment(), null, factory);
+    }
+
+    public List<WritableElement> parseAll(TypeElement typeElement) {
+        List<WritableElement> generatedMethods = new ArrayList<>();
+        parseElement(generatedMethods, typeElement);
+
+        List<? extends ExecutableElement> methods = ElementFilter.methodsIn(typeElement.getEnclosedElements());
+        for (ExecutableElement method : methods) {
+            for (VariableElement var : method.getParameters()) {
+                parseElement(generatedMethods, var);
+            }
+            parseElement(generatedMethods, method);
+        }
+
+        return generatedMethods;
+    }
+
+    private void parseElement(List<WritableElement> elements, Element element) {
+        List<? extends AnnotationMirror> mirrors = element.getAnnotationMirrors();
+        for (AnnotationMirror mirror : mirrors) {
+            ExtensionProcessor processor = findProcessor(element, mirror);
+            if (processor != null) {
+                try {
+                    factory.generatorAnnotationMirror = mirror;
+                    factory.generatorElement = element;
+                    processor.process(extensionContext, mirror, element);
+                    elements.addAll(extensionContext.returnElements());
+                } catch (Throwable e) {
+                    context.getLog().error(element, mirror, "Processor for '%s' failed with exception: \n\n%s.", Utils.getQualifiedName(mirror.getAnnotationType()), Utils.printException(e));
+                } finally {
+                    factory.generatorAnnotationMirror = null;
+                    factory.generatorElement = null;
+                }
+            }
+        }
+    }
+
+    private ExtensionProcessor findProcessor(Element element, AnnotationMirror mirror) {
+        String processorName = Utils.getQualifiedName(mirror.getAnnotationType());
+        ExtensionProcessor processor = null;
+        if (extensions.containsKey(processorName)) {
+            processor = extensions.get(processorName);
+        } else {
+            AnnotationMirror foundExtension = Utils.findAnnotationMirror(context.getEnvironment(), mirror.getAnnotationType().asElement(), ExtensionAnnotation.class);
+            if (foundExtension != null) {
+                String className = Utils.getAnnotationValueString(foundExtension, "processorClassName");
+                Class<?> processorClass;
+                try {
+                    processorClass = Class.forName(className);
+                } catch (ClassNotFoundException e) {
+                    context.getLog().error(element, mirror, "Could not find processor class '%s' configured in '@%s'.", className, processorName);
+                    return null;
+                }
+                try {
+                    processor = (ExtensionProcessor) processorClass.newInstance();
+                } catch (InstantiationException e) {
+                    context.getLog().error(element, mirror, "Could not instantiate processor class '%s' configured in '@%s'.", className, processorName);
+                    return null;
+                } catch (IllegalAccessException e) {
+                    context.getLog().error(element, mirror, "Could not access processor class '%s' configured in '@%s'.", className, processorName);
+                    return null;
+                } catch (ClassCastException e) {
+                    context.getLog().error(element, mirror, "Processor class '%s' configured in '@%s' does not implement '%s'.", className, processorName, ExtensionProcessor.class.getName());
+                    return null;
+                }
+            }
+            extensions.put(processorName, processor);
+        }
+        return processor;
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/GenericParser.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.operation;
+
+import java.lang.annotation.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
+
+public class GenericParser extends OperationMethodParser<SpecializationData> {
+
+    public GenericParser(ProcessorContext context, OperationData operation) {
+        super(context, operation);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        return createDefaultMethodSpec(null);
+    }
+
+    @Override
+    protected ParameterSpec createValueParameterSpec(String valueName) {
+        return new ParameterSpec(valueName, getOperation().getTypeSystem().getGenericType(), Kind.EXECUTE, false);
+    }
+
+    @Override
+    protected ParameterSpec createReturnParameterSpec() {
+        return new ParameterSpec("returnValue", getOperation().getTypeSystem(), Kind.EXECUTE, false, Cardinality.ONE);
+    }
+
+    @Override
+    public SpecializationData create(TemplateMethod method) {
+        return new SpecializationData(method, true, false);
+    }
+
+    @Override
+    public Class< ? extends Annotation> getAnnotationType() {
+        return Generic.class;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationCodeGenerator.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,903 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.operation;
+
+import static com.oracle.truffle.codegen.processor.Utils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.ast.*;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
+import com.oracle.truffle.codegen.processor.typesystem.*;
+
+public class OperationCodeGenerator extends CompilationUnitFactory<OperationData> {
+
+    private static final String OPERATION_FIELD_NAME =  "operation";
+
+    public OperationCodeGenerator(ProcessorContext context) {
+        super(context);
+    }
+
+    private TypeMirror getUnexpectedValueException() {
+        return getContext().getTruffleTypes().getUnexpectedValueException();
+    }
+
+    private static String operationClassName(OperationData operation) {
+        return Utils.getSimpleName(operation.getTemplateType().asType());
+    }
+
+    private static String factoryClassName(OperationData operation) {
+        return operationClassName(operation) + "Factory";
+    }
+
+    private static String nodeClassName(OperationData operation) {
+        String name = operationClassName(operation);
+        if (name.length() > 2 && name.endsWith("Op")) {
+            name = name.substring(0, name.length() - 2);
+        }
+        return name + "Node";
+    }
+
+    private static String nodeClassName(SpecializationData specialization) {
+        String name = "";
+        if (specialization.getOperation().getAllMethods().length > 1) {
+            name = specialization.getMethodName();
+            if (name.startsWith("do")) {
+                name = name.substring(2);
+            }
+        }
+        return name + nodeClassName(specialization.getOperation());
+    }
+
+    private static String nodeVariableName(ParameterSpec spec) {
+        if (spec.getKind() == Kind.EXECUTE) {
+            return spec.getName() + "Node";
+        }
+        return spec.getName();
+    }
+
+    private static String nodeVariableName(ActualParameter param) {
+        return nodeVariableName(param.getSpecification());
+    }
+
+    private static String valueVariableName(ParameterSpec spec) {
+        if (spec.getKind() == Kind.EXECUTE) {
+            return spec.getName() + "Value";
+        }
+        return spec.getName();
+    }
+
+    private static String valueVariableName(ActualParameter param) {
+        return valueVariableName(param.getSpecification());
+    }
+
+    public static String executeMethodName(TypeData type) {
+        if (type.isGeneric()) {
+            return "executeGeneric";
+        }
+        return "execute" + Utils.getSimpleName(type.getBoxedType());
+    }
+
+    private static EnumSet<Kind> kinds(Kind... values) {
+        EnumSet<Kind> result = EnumSet.noneOf(Kind.class);
+        for (Kind value : values) {
+            result.add(value);
+        }
+        return result;
+    }
+
+    private static void addNodeParameters(CodeExecutableElement method, OperationData operation, EnumSet<Kind> included) {
+        for (ParameterSpec spec : operation.getSpecification().getParameters()) {
+            if (included.contains(spec.getKind())) {
+                if (spec.getKind() == Kind.EXECUTE) {
+                    method.addParameter(new CodeVariableElement(operation.getTypeSystem().getNodeType(), nodeVariableName(spec)));
+                } else {
+                    method.addParameter(new CodeVariableElement(spec.getValueType(), nodeVariableName(spec)));
+                }
+            }
+        }
+        if (included.contains(Kind.CONSTRUCTOR_FIELD)) {
+            for (OperationFieldData field : operation.getConstructorFields()) {
+                method.addParameter(new CodeVariableElement(field.getJavaClass(), field.getName()));
+            }
+        }
+    }
+
+    private static void addValueParameters(CodeExecutableElement method, OperationData operation, EnumSet<Kind> included) {
+        for (ParameterSpec spec : operation.getSpecification().getParameters()) {
+            if (included.contains(spec.getKind())) {
+                method.addParameter(new CodeVariableElement(spec.getValueType(), valueVariableName(spec)));
+            }
+        }
+        if (included.contains(Kind.CONSTRUCTOR_FIELD)) {
+            for (OperationFieldData field : operation.getConstructorFields()) {
+                method.addParameter(new CodeVariableElement(field.getJavaClass(), field.getName()));
+            }
+        }
+    }
+
+    private static void addOperationFieldName(CodeTreeBuilder body, OperationData operation) {
+        if (!operation.isUseSingleton()) {
+            body.string(OPERATION_FIELD_NAME);
+        }
+    }
+
+    private static void addOperationVariable(Set<Modifier> modifiers, Element element, OperationData operation, CodeTypeElement operationGen) {
+        if (!operation.isUseSingleton()) {
+            TypeMirror type = findOperationType(operation, operationGen);
+            if (element instanceof CodeExecutableElement) {
+                ((CodeExecutableElement) element).addParameter(new CodeVariableElement(modifiers, type, OPERATION_FIELD_NAME));
+            } else if (element instanceof CodeTypeElement) {
+                ((CodeTypeElement) element).add(new CodeVariableElement(modifiers, type, OPERATION_FIELD_NAME));
+            }
+        }
+    }
+
+    private static void addNodeNames(CodeTreeBuilder body, OperationData operation, EnumSet<Kind> included) {
+        for (ParameterSpec spec : operation.getSpecification().getParameters()) {
+            if (included.contains(spec.getKind())) {
+                body.string(nodeVariableName(spec));
+            }
+        }
+        if (included.contains(Kind.CONSTRUCTOR_FIELD)) {
+            for (OperationFieldData field : operation.getConstructorFields()) {
+                body.string(field.getName());
+            }
+        }
+    }
+
+    private static void addValueNames(CodeTreeBuilder body, OperationData operation, EnumSet<Kind> included) {
+        for (ParameterSpec spec : operation.getSpecification().getParameters()) {
+            if (included.contains(spec.getKind())) {
+                body.string(valueVariableName(spec));
+            }
+        }
+        if (included.contains(Kind.CONSTRUCTOR_FIELD)) {
+            for (OperationFieldData field : operation.getConstructorFields()) {
+                body.string(field.getName());
+            }
+        }
+    }
+
+    private static void addValueNamesWithCasts(ProcessorContext context, CodeTreeBuilder body, SpecializationData specialization, EnumSet<Kind> included) {
+        for (ActualParameter spec : specialization.getParameters()) {
+            if (included.contains(spec.getSpecification().getKind())) {
+                TypeData typeData = spec.getActualTypeData(specialization.getOperation().getTypeSystem());
+                if (typeData.isGeneric()) {
+                    body.string(valueVariableName(spec));
+                } else {
+                    String methodName = TypeSystemCodeGenerator.asTypeMethodName(typeData);
+                    startCallTypeSystemMethod(context, body, specialization.getOperation(), methodName);
+                    body.string(valueVariableName(spec));
+                    body.end().end();
+                }
+            }
+        }
+    }
+
+    public static VariableElement findSingleton(ProcessorContext context, OperationData operation) {
+        TypeMirror type = context.findGeneratedClassBySimpleName(OperationCodeGenerator.genClassName(operation), operation);
+        return Utils.findDeclaredField(type, OperationCodeGenerator.singletonName(operation));
+    }
+
+    private static TypeMirror findOperationType(OperationData operation, CodeTypeElement operationGen) {
+        if (operation.hasExtensions()) {
+            // return generated type
+            return operationGen.asType();
+        } else {
+            // return default type
+            return operation.getTemplateType().asType();
+        }
+    }
+
+    private static String genClassName(OperationData operation) {
+        String name = getSimpleName(operation.getTemplateType());
+        return name + "Gen";
+    }
+
+    private static String singletonName(OperationData operation) {
+        return createConstantName(getSimpleName(operation.getTemplateType().asType()));
+    }
+
+    private static void startCallOperationMethod(CodeTreeBuilder body, OperationData operation, TemplateMethod method) {
+        body.startGroup();
+
+        if (operation.isUseSingleton()) {
+            body.string(singletonName(operation));
+            body.string(".").startCall(method.getMethodName());
+        } else {
+            body.string(OPERATION_FIELD_NAME);
+            body.string(".");
+            body.startCall(method.getMethodName());
+        }
+    }
+
+    private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body,  OperationData operation, String methodName) {
+        VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, operation.getTypeSystem());
+        assert singleton != null;
+
+        body.startGroup();
+        body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString());
+        body.string(".").startCall(methodName);
+    }
+
+    private static void emitGuards(ProcessorContext context, CodeTreeBuilder body, String prefix, SpecializationData specialization, boolean onSpecialization, boolean needsCast) {
+        // Implict guards based on method signature
+        String andOperator = prefix;
+        for (ActualParameter param : specialization.getParameters()) {
+            if (param.getSpecification().getKind() == Kind.EXECUTE && !param.getActualTypeData(specialization.getOperation().getTypeSystem()).isGeneric()) {
+                body.string(andOperator);
+                startCallTypeSystemMethod(context, body, specialization.getOperation(),
+                                TypeSystemCodeGenerator.isTypeMethodName(param.getActualTypeData(specialization.getOperation().getTypeSystem())));
+                body.string(valueVariableName(param));
+                body.end().end(); // call
+                andOperator = " && ";
+            }
+        }
+
+        if (specialization.getGuards().length > 0) {
+            // Explicitly specified guards
+            for (SpecializationGuardData guard : specialization.getGuards()) {
+                if ((guard.isOnSpecialization() && onSpecialization)
+                                || (guard.isOnExecution() && !onSpecialization)) {
+                    body.string(andOperator);
+
+                    if (guard.getGuardDeclaration().getOrigin() == specialization.getOperation()) {
+                        startCallOperationMethod(body, specialization.getOperation(), guard.getGuardDeclaration());
+                    } else {
+                        startCallTypeSystemMethod(context, body, specialization.getOperation(), guard.getGuardMethod());
+                    }
+
+                    if (needsCast) {
+                        addValueNamesWithCasts(context, body, specialization, kinds(Kind.EXECUTE, Kind.SHORT_CIRCUIT));
+                    } else {
+                        addValueNames(body, specialization.getOperation(), kinds(Kind.EXECUTE, Kind.SHORT_CIRCUIT));
+                    }
+                    body.end().end(); // call
+                    andOperator = " && ";
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void createChildren(OperationData m) {
+        CodeTypeElement operationGen = null;
+        if (m.hasExtensions()) {
+            OperationGenFactory factory = new OperationGenFactory(context);
+            add(factory, m);
+            operationGen = (CodeTypeElement) factory.getElement();
+        }
+        if (m.generateFactory) {
+            add(new OperationNodeFactory(context, operationGen), m);
+        }
+    }
+
+    protected class OperationGenFactory extends ClassElementFactory<OperationData> {
+
+        public OperationGenFactory(ProcessorContext context) {
+            super(context);
+        }
+
+        @Override
+        protected CodeTypeElement create(OperationData operation) {
+            CodeTypeElement clazz = createClass(operation, modifiers(PUBLIC), genClassName(operation), operation.getTemplateType().asType(), false);
+
+            clazz.add(createConstructorUsingFields(modifiers(PUBLIC), clazz));
+
+            if (operation.getExtensionElements() != null) {
+                clazz.getEnclosedElements().addAll(operation.getExtensionElements());
+            }
+            return clazz;
+        }
+
+    }
+
+
+
+    protected class OperationNodeFactory extends ClassElementFactory<OperationData> {
+
+        private final CodeTypeElement operationGen;
+
+        public OperationNodeFactory(ProcessorContext context, CodeTypeElement operationGen) {
+            super(context);
+            this.operationGen = operationGen;
+        }
+
+        @Override
+        protected CodeTypeElement create(OperationData operation) {
+            CodeTypeElement clazz = createClass(operation, modifiers(PUBLIC, FINAL), factoryClassName(operation), null, false);
+
+            if (operation.isUseSingleton()) {
+                TypeMirror type = findOperationType(operation, operationGen);
+                CodeVariableElement singleton = new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), type, singletonName(operation));
+                clazz.add(singleton);
+                CodeTreeBuilder singletonInit = singleton.createInitBuilder();
+                singletonInit.startNew(type).end();
+            }
+
+            clazz.add(createConstructorUsingFields(modifiers(PRIVATE), clazz));
+            clazz.add(createCreateMethod(operation));
+            if (operation.getAllMethods().length > 1) {
+                clazz.add(createCreateSpecializedMethod(operation));
+            }
+            if (operation.needsRewrites()) {
+                clazz.add(createSpecializeMethod(operation));
+                clazz.add(createGeneratedGenericMethod(operation));
+            }
+
+            return clazz;
+        }
+
+        @Override
+        protected void createChildren(OperationData operation) {
+            for (SpecializationData specialization : operation.getAllMethods()) {
+                add(new SpecializationNodeFactory(context, operationGen), specialization);
+            }
+        }
+
+        private CodeExecutableElement createCreateMethod(OperationData operation) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), operation.getNodeType(), "create");
+            addNodeParameters(method, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE, Kind.CONSTRUCTOR_FIELD));
+
+            CodeTreeBuilder body = method.createBuilder();
+            body.startReturn();
+            if (operation.getAllMethods().length == 0) {
+                body.null_();
+            } else {
+                body.startNew(nodeClassName(operation.getAllMethods()[0]));
+                emitNewOperation(body, operation);
+                addNodeNames(body, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
+                body.end();
+            }
+            body.end();
+
+            return method;
+        }
+
+        private void emitNewOperation(CodeTreeBuilder body, OperationData operation) {
+            if (!operation.isUseSingleton()) {
+                body.startGroup();
+                if (operation.hasExtensions()) {
+                    body.startNew(genClassName(operation));
+                } else {
+                    body.startNew(operation.getTemplateType().asType());
+                }
+                addNodeNames(body, operation, kinds(Kind.CONSTRUCTOR_FIELD));
+                body.end();
+                body.end();
+            }
+        }
+
+        private CodeExecutableElement createCreateSpecializedMethod(OperationData operation) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), operation.getNodeType(), "createSpecialized");
+            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "specializationClass"));
+            addOperationVariable(modifiers(), method, operation, operationGen);
+            addNodeParameters(method, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
+
+            CodeTreeBuilder body = method.createBuilder();
+
+            boolean first = true;
+            for (TypeData type : operation.getTypeSystem().getTypes()) {
+                SpecializationData specialization = operation.findUniqueSpecialization(type);
+                if (specialization != null && !type.isGeneric()) {
+                    if (first) {
+                        body.startIf();
+                        first = false;
+                    } else {
+                        body.startElseIf();
+                    }
+                    body.string("specializationClass == ").type(type.getBoxedType()).string(".class").end().startBlock();
+                    body.startReturn().startNew(nodeClassName(specialization));
+                    addOperationFieldName(body, operation);
+                    addNodeNames(body, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
+                    body.end().end();
+                    body.end();
+                }
+            }
+            body.startReturn().startNew(nodeClassName(operation.getGenericSpecialization()));
+            addOperationFieldName(body, operation);
+            addNodeNames(body, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
+            body.end().end();
+            return method;
+        }
+
+        private CodeExecutableElement createSpecializeMethod(OperationData operation) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), operation.getNodeType(), "specialize");
+            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState"));
+            addOperationVariable(modifiers(), method, operation, operationGen);
+            addValueParameters(method, operation, kinds(Kind.EXECUTE));
+            addNodeParameters(method, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
+
+            CodeTreeBuilder body = method.createBuilder();
+            body.startStatement().string("boolean allowed = (minimumState == ").string(nodeClassName(operation.getAllMethods()[0])).string(".class)").end();
+
+            for (int i = 1; i < operation.getAllMethods().length; i++) {
+                SpecializationData specialization = operation.getAllMethods()[i];
+                body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeClassName(specialization)).string(".class)").end();
+
+                if (specialization.isGeneric()) {
+                    body.startIf().string("allowed").end().startBlock();
+                } else {
+                    body.startIf().string("allowed");
+                    emitGuards(getContext(), body, " && ", specialization, true, true);
+                    body.end().startBlock();
+                }
+                body.startReturn().startNew(nodeClassName(specialization));
+
+                addOperationFieldName(body, operation);
+                addNodeNames(body, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
+                body.end().end();
+                body.end(); // block
+            }
+            body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end();
+
+            return method;
+        }
+
+
+        private void emitInvokeDoMethod(CodeTreeBuilder builder, SpecializationData specialization) {
+            if (specialization.getExceptions().length > 0) {
+                builder.startTryBlock();
+            }
+
+            builder.startReturn();
+            startCallOperationMethod(builder, specialization.getOperation(), specialization);
+            for (ActualParameter param : specialization.getParameters()) {
+                boolean needsCast = param.getSpecification().getKind() == Kind.EXECUTE && !param.getActualTypeData(specialization.getOperation().getTypeSystem()).isGeneric();
+                if (needsCast) {
+                    startCallTypeSystemMethod(getContext(), builder, specialization.getOperation(), TypeSystemCodeGenerator.asTypeMethodName(param.getActualTypeData(specialization.getOperation().getTypeSystem())));
+                }
+                builder.string(valueVariableName(param));
+                if (needsCast) {
+                    builder.end().end();
+                }
+            }
+            builder.end().end(); // start call operation
+            builder.end(); // return
+
+            if (specialization.getExceptions().length > 0) {
+                for (SpecializationThrowsData exception : specialization.getExceptions()) {
+                    builder.end().startCatchBlock(exception.getJavaClass(), "ex");
+                    emitInvokeDoMethod(builder, exception.getTransitionTo());
+                }
+                builder.end();
+            }
+        }
+
+        private CodeExecutableElement createGeneratedGenericMethod(OperationData operation) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), operation.getGenericSpecialization().getReturnType().getActualType(), "generatedGeneric");
+            addOperationVariable(modifiers(), method, operation, operationGen);
+            addValueParameters(method, operation, kinds(Kind.SIGNATURE, Kind.EXECUTE, Kind.SHORT_CIRCUIT, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
+
+            CodeTreeBuilder builder = method.createBuilder();
+            boolean ifStarted = false;
+            for (int i = 0; i < operation.getSpecializations().length; i++) {
+                SpecializationData specialization = operation.getSpecializations()[i];
+                if (specialization.isUninitialized()) {
+                    continue;
+                }
+                if (!specialization.isGeneric()) {
+                    if (!ifStarted) {
+                        builder.startIf();
+                        ifStarted = true;
+                    } else {
+                        builder.startElseIf();
+                    }
+                    emitGuards(getContext(), builder, "", specialization, false, true);
+                    builder.end().startBlock();
+                } else {
+                    builder.startElseBlock();
+                }
+
+                emitInvokeDoMethod(builder, specialization);
+                builder.end();
+            }
+            return method;
+        }
+    }
+
+    protected class SpecializationNodeFactory extends ClassElementFactory<SpecializationData> {
+
+        private CodeTypeElement operationGen;
+
+        public SpecializationNodeFactory(ProcessorContext context, CodeTypeElement operationGen) {
+            super(context);
+            this.operationGen = operationGen;
+        }
+
+        @Override
+        public CodeTypeElement create(SpecializationData specialization) {
+            OperationData operation = specialization.getOperation();
+            CodeTypeElement clazz = createClass(operation, modifiers(PRIVATE, STATIC, FINAL), nodeClassName(specialization), operation.getNodeType(), false);
+
+
+            CodeExecutableElement constructor = new CodeExecutableElement(modifiers(PROTECTED), null, clazz.getSimpleName().toString());
+            clazz.add(constructor);
+
+            CodeTreeBuilder builder = constructor.createBuilder();
+            builder.startStatement().startSuperCall();
+            addNodeNames(builder, operation, kinds(Kind.SUPER_ATTRIBUTE));
+            builder.end().end();
+
+            if (!operation.isUseSingleton()) {
+                addOperationVariable(modifiers(), constructor, operation, operationGen);
+                addOperationVariable(modifiers(PRIVATE, FINAL), clazz, operation, operationGen);
+                builder.startStatement();
+                builder.string("this.");
+                addOperationFieldName(builder, operation);
+                builder.string(" = ");
+                addOperationFieldName(builder, operation);
+                builder.end();
+            }
+            addNodeParameters(constructor, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
+
+
+            for (ParameterSpec spec : operation.getSpecification().getParameters()) {
+                String name = nodeVariableName(spec);
+
+                boolean isNodeAttribute = spec.getKind() == Kind.ATTRIBUTE && getContext().getEnvironment().getTypeUtils().isAssignable(spec.getValueType(), getContext().getTruffleTypes().getNode());
+                boolean isNodeArrayAttribute = spec.getKind() == Kind.ATTRIBUTE &&
+                                getContext().getEnvironment().getTypeUtils().isAssignable(spec.getValueType(), getContext().getTruffleTypes().getNodeArray());
+                if (spec.getKind() == Kind.EXECUTE || isNodeAttribute || isNodeArrayAttribute) {
+                    CodeVariableElement field = new CodeVariableElement(modifiers(PRIVATE), operation.getTypeSystem().getNodeType(), name);
+                    clazz.add(field);
+                    field.addAnnotationMirror(new CodeAnnotationMirror((DeclaredType) getContext().getTruffleTypes().getStableAnnotation()));
+                    if (isNodeArrayAttribute) {
+                        field.addAnnotationMirror(new CodeAnnotationMirror((DeclaredType) getContext().getTruffleTypes().getContentStableAnnotation()));
+                    }
+                    builder.startStatement().string("this.").string(name).string(" = adoptChild(").string(name).string(")").end();
+                } else if (spec.getKind() == Kind.ATTRIBUTE) {
+                    clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), spec.getValueType(), name));
+                    builder.startStatement().string("this.").string(name).string(" = ").string(name).end();
+                }
+            }
+
+            TypeSystemData typeSystem = operation.getTypeSystem();
+            for (TypeData type : typeSystem.getTypes()) {
+                CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), executeMethodName(type));
+                clazz.add(method);
+                addValueParameters(method, operation, kinds(Kind.SIGNATURE));
+                if (!type.isGeneric()) {
+                    method.addThrownType(getUnexpectedValueException());
+                }
+
+                if (specialization.getReturnType().getActualTypeData(typeSystem) == type) {
+                    buildFunctionalExecuteMethod(method.createBuilder(), operation, specialization);
+                } else {
+                    buildCastingExecuteMethod(method.createBuilder(), operation, specialization, type);
+                }
+            }
+
+            if (typeSystem.getVoidType() != null)  {
+                CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), typeSystem.getVoidType().getPrimitiveType(), executeMethodName(typeSystem.getVoidType()));
+                addValueParameters(method, operation, kinds(Kind.SIGNATURE));
+                buildCastingExecuteMethod(method.createBuilder(), operation, specialization, typeSystem.getVoidType());
+                clazz.add(method);
+            }
+
+            if (operation.needsRewrites() && !specialization.isGeneric() && !specialization.isUninitialized()) {
+                buildSpecializeStateMethod(clazz, operation);
+            }
+            buildSpecializeClassMethod(clazz, operation);
+
+            return clazz;
+        }
+
+        private void buildCastingExecuteMethod(CodeTreeBuilder builder, OperationData operation, SpecializationData specialization, TypeData type) {
+            if (!type.isVoid()) {
+                builder.startStatement().type(specialization.getReturnType().getActualType()).string(" result").end();
+            }
+
+            boolean needsTry = !specialization.getReturnType().getActualTypeData(operation.getTypeSystem()).isGeneric();
+            if (needsTry) {
+                builder.startTryBlock();
+            }
+
+            builder.startStatement();
+            if (!type.isVoid()) {
+                builder.string("result = ");
+            }
+            builder.startCall(executeMethodName(specialization.getReturnType().getActualTypeData(operation.getTypeSystem()))).string("frame").end();
+            builder.end(); // statement
+
+            if (needsTry) {
+                builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
+
+                if (!type.isVoid()) {
+                    builder.startReturn();
+                    if (!type.isGeneric()) {
+                        startCallTypeSystemMethod(getContext(), builder, operation, TypeSystemCodeGenerator.expectTypeMethodName(type));
+                    }
+
+                    builder.string("ex.getResult()");
+
+                    if (!type.isGeneric()) {
+                        builder.end().end();
+                    }
+                    builder.end(); // return
+                } else {
+                    builder.string("// ignore").newLine();
+                }
+            }
+            builder.end(); // try/catch
+
+            if (!type.isVoid()) {
+                builder.startReturn();
+                if (!type.isGeneric()) {
+                    startCallTypeSystemMethod(getContext(), builder, operation, TypeSystemCodeGenerator.expectTypeMethodName(type));
+                }
+                builder.string("result");
+                if (!type.isGeneric()) {
+                    builder.end().end();
+                }
+                builder.end(); // return
+            }
+        }
+
+        private void buildFunctionalExecuteMethod(CodeTreeBuilder builder, OperationData operation, SpecializationData specialization) {
+            ActualParameter previousShortCircuitParameter = null;
+            for (ActualParameter param : specialization.getParameters()) {
+                if (param.getSpecification().getKind() != Kind.EXECUTE) {
+                    // Nothing to do.
+                } else if (param.getActualTypeData(operation.getTypeSystem()).isGeneric()) {
+                    buildGenericValueExecute(builder, operation, param, null);
+                } else {
+                    buildSpecializedValueExecute(builder, operation, specialization, param);
+                }
+
+                assert param.getSpecification().getKind() == Kind.SHORT_CIRCUIT || previousShortCircuitParameter == null;
+            }
+
+            if (specialization.hasDynamicGuards()) {
+                builder.startIf();
+                emitGuards(getContext(), builder, "", specialization, false, false);
+                builder.end().startBlock();
+            }
+            if (specialization.getExceptions().length > 0) {
+                builder.startTryBlock();
+            }
+
+            if (specialization.isUninitialized() && operation.needsRewrites()) {
+                for (TemplateMethod listener : operation.getSpecializationListeners()) {
+                    builder.startStatement();
+                    startCallOperationMethod(builder, operation, listener);
+                    for (ActualParameter param : listener.getParameters()) {
+                        builder.string(valueVariableName(param));
+                    }
+                    builder.end().end();
+                    builder.end(); // statement
+                }
+
+                builder.startStatement();
+                builder.startCall("replace");
+                builder.startCall(factoryClassName(operation), "specialize");
+                builder.typeLiteral(builder.getRoot().getEnclosingClass().asType());
+                addOperationFieldName(builder, operation);
+                addValueNames(builder, operation, kinds(Kind.EXECUTE));
+                addNodeNames(builder, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
+                builder.end().end().end();
+            }
+
+            if ((specialization.isUninitialized() || specialization.isGeneric()) && operation.needsRewrites()) {
+                builder.startReturn().startCall(factoryClassName(specialization.getOperation()), "generatedGeneric");
+                addOperationFieldName(builder, operation);
+                addValueNames(builder, operation, kinds(Kind.SIGNATURE, Kind.EXECUTE, Kind.SHORT_CIRCUIT, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
+                builder.end().end();
+            } else {
+                builder.startReturn();
+
+                if (specialization.isUninitialized()) {
+                    startCallOperationMethod(builder, specialization.getOperation(), specialization.getOperation().getGenericSpecialization());
+                } else {
+                    startCallOperationMethod(builder, specialization.getOperation(), specialization);
+                }
+                for (ActualParameter param : specialization.getParameters()) {
+                    builder.string(valueVariableName(param));
+                }
+                builder.end().end(); // operation call
+                builder.end(); // return
+            }
+
+            if (specialization.getExceptions().length > 0) {
+                for (SpecializationThrowsData exception : specialization.getExceptions()) {
+                    builder.end().startCatchBlock(exception.getJavaClass(), "ex");
+                    buildThrowSpecialize(builder, operation, exception.getTransitionTo(), null);
+                }
+                builder.end();
+            }
+            if (specialization.hasDynamicGuards()) {
+                builder.end().startElseBlock();
+                buildThrowSpecialize(builder, operation, specialization.findNextSpecialization(), null);
+                builder.end();
+            }
+        }
+
+        private void buildGenericValueExecute(CodeTreeBuilder builder, OperationData operation, ActualParameter param, ParameterSpec exceptionSpec) {
+            boolean shortCircuit = startShortCircuit(builder, operation.getGenericSpecialization(),
+                            operation.getGenericSpecialization().findParameter(param.getSpecification().getName()), exceptionSpec);
+
+            builder.startStatement();
+            if (!shortCircuit) {
+                builder.type(operation.getTypeSystem().getGenericType());
+                builder.string(" ");
+            }
+            builder.string(valueVariableName(param));
+            builder.string(" = ").startCall(nodeVariableName(param), executeMethodName(operation.getTypeSystem().getGenericTypeData())).string("frame").end();
+            builder.end();
+
+            endShortCircuit(builder, shortCircuit);
+        }
+
+        private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization,
+                        ActualParameter forParam, ParameterSpec exceptionParam) {
+            ActualParameter shortCircuitParam = specialization.getPreviousParam(forParam);
+            if (shortCircuitParam == null || shortCircuitParam.getSpecification().getKind() != Kind.SHORT_CIRCUIT) {
+                return false;
+            }
+
+            int shortCircuitIndex = 0;
+            for (ActualParameter parameter : specialization.getParameters()) {
+                if (parameter.getSpecification().getKind() == Kind.SHORT_CIRCUIT) {
+                    if (parameter == shortCircuitParam) {
+                        break;
+                    }
+                    shortCircuitIndex++;
+                }
+            }
+
+            builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(shortCircuitParam.getSpecification().getName()).string(" = ");
+            ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex];
+
+            startCallOperationMethod(builder, specialization.getOperation(), shortCircuitData);
+            for (ActualParameter callParam : shortCircuitData.getParameters()) {
+                ParameterSpec spec = callParam.getSpecification();
+                if (spec.getKind() == Kind.EXECUTE || spec.getKind() == Kind.SHORT_CIRCUIT || spec.getKind() == Kind.SIGNATURE) {
+                    if (exceptionParam != null && callParam.getSpecification().getName().equals(exceptionParam.getName())) {
+                        builder.string("ex.getResult()");
+                    } else {
+                        builder.string(valueVariableName(spec));
+                    }
+                }
+            }
+            builder.end().end(); // call operation
+
+            builder.end(); // statement
+
+            builder.declaration(forParam.getActualType(), valueVariableName(forParam),
+                            CodeTreeBuilder.createBuilder().defaultValue(forParam.getActualType()));
+            builder.startIf().string(valueVariableName(shortCircuitParam)).end();
+            builder.startBlock();
+
+            return true;
+        }
+
+
+        private void endShortCircuit(CodeTreeBuilder builder, boolean shortCircuit) {
+            if (shortCircuit) {
+                builder.end();
+            }
+        }
+
+        private void buildSpecializedValueExecute(CodeTreeBuilder builder, OperationData operation, SpecializationData specialization, ActualParameter param) {
+            boolean shortCircuit = startShortCircuit(builder, specialization, param, null);
+
+            if (!shortCircuit) {
+                builder.startStatement().type(param.getActualType()).string(" ").string(valueVariableName(param)).end();
+            }
+
+            builder.startTryBlock();
+            builder.startStatement().string(valueVariableName(param)).string(" = ");
+            builder.startCall(nodeVariableName(param), executeMethodName(param.getActualTypeData(operation.getTypeSystem()))).string("frame").end();
+            builder.end();
+
+            builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
+            boolean execute = false;
+            for (ActualParameter exParam : specialization.getParameters()) {
+                if (exParam.getSpecification().getKind() != Kind.EXECUTE) {
+                    // Nothing to do.
+                } else if (execute) {
+                    buildGenericValueExecute(builder, operation, exParam, param.getSpecification());
+                } else if (exParam == param) {
+                    execute = true;
+                }
+            }
+
+            buildThrowSpecialize(builder, operation, specialization.findNextSpecialization(), param.getSpecification());
+            builder.end(); // catch block
+
+            endShortCircuit(builder, shortCircuit);
+            builder.newLine();
+        }
+
+        private void buildThrowSpecialize(CodeTreeBuilder builder, OperationData operation, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) {
+            builder.startThrow().startCall("specialize");
+            builder.string(nodeClassName(nextSpecialization) + ".class");
+            addValueNames(builder, operation, kinds(Kind.SIGNATURE));
+            for (ParameterSpec spec : operation.getSpecification().getParameters()) {
+                if (spec.getKind() == Kind.EXECUTE || spec.getKind() == Kind.SHORT_CIRCUIT) {
+                    if (spec == exceptionSpec) {
+                        builder.string("ex.getResult()");
+                    } else {
+                        builder.string(valueVariableName(spec));
+                    }
+                }
+            }
+            builder.end().end();
+        }
+
+        private void buildSpecializeStateMethod(CodeTypeElement clazz, OperationData operation) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), getUnexpectedValueException(), "specialize");
+            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState"));
+            addValueParameters(method, operation, kinds(Kind.SIGNATURE, Kind.EXECUTE, Kind.SHORT_CIRCUIT));
+            clazz.add(method);
+            CodeTreeBuilder builder = method.createBuilder();
+
+            for (TemplateMethod listener : operation.getSpecializationListeners()) {
+                builder.startStatement();
+                startCallOperationMethod(builder, operation, listener);
+                for (ActualParameter param : listener.getParameters()) {
+                    builder.string(valueVariableName(param));
+                }
+                builder.end().end();
+                builder.end(); // statement
+            }
+
+            builder.startStatement();
+            builder.startCall("replace");
+            builder.startCall(factoryClassName(operation), "specialize").string("minimumState");
+            addOperationFieldName(builder, operation);
+            addValueNames(builder, operation, kinds(Kind.EXECUTE));
+            addNodeNames(builder, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
+            builder.end().end().end();
+
+            builder.startReturn().startNew(getUnexpectedValueException()).startCall(factoryClassName(operation), "generatedGeneric");
+            addOperationFieldName(builder, operation);
+            addValueNames(builder, operation, kinds(Kind.SIGNATURE, Kind.EXECUTE, Kind.SHORT_CIRCUIT, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
+            builder.end().end().end();
+        }
+
+        private void buildSpecializeClassMethod(CodeTypeElement clazz, OperationData operation) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getContext().getType(void.class), "specialize");
+            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "specializationClass"));
+            if (!isDeclaredMethodInSuperType(clazz, method.getSimpleName().toString(), method.getParameterTypes())) {
+                return;
+            }
+            clazz.add(method);
+            CodeTreeBuilder builder = method.createBuilder();
+
+            builder.startStatement();
+            builder.startCall("replace");
+            builder.startCall(factoryClassName(operation), "createSpecialized").string("specializationClass");
+            addOperationFieldName(builder, operation);
+            addNodeNames(builder, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE));
+            builder.end().end().end();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationData.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.operation;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.typesystem.*;
+
+public class OperationData extends Template {
+
+    private final TypeSystemData typeSystem;
+    private final String[] values;
+    private final String[] shortCircuitValues;
+    private final OperationFieldData[] operationFields;
+    private final OperationFieldData[] constructorFields;
+    private final OperationFieldData[] superFields;
+    private final TypeMirror nodeType;
+
+    private MethodSpec specification;
+    private SpecializationData genericSpecialization;
+    private SpecializationData[] specializations;
+    private TemplateMethod[] specializationListeners;
+    private GuardData[] guards;
+
+    boolean generateFactory = true;
+
+    public OperationData(TypeElement templateType, AnnotationMirror templateTypeAnnotation,
+                    TypeSystemData typeSystem, TypeMirror nodeType,
+                    String[] values, String[] shortCircuitValues,
+                    OperationFieldData[] operationFields,
+                    OperationFieldData[] constructorFields,
+                    OperationFieldData[] superFields) {
+        super(templateType, templateTypeAnnotation);
+        this.nodeType = nodeType;
+        this.typeSystem = typeSystem;
+        this.values = values;
+        this.shortCircuitValues = shortCircuitValues;
+        this.operationFields = operationFields;
+        this.constructorFields = constructorFields;
+        this.superFields = superFields;
+    }
+
+    public boolean isUseSingleton() {
+        return constructorFields.length == 0;
+    }
+
+    public boolean hasExtensions() {
+        return !getExtensionElements().isEmpty();
+    }
+
+    public List<GuardData> findGuards(String name) {
+        List<GuardData> foundGuards = new ArrayList<>();
+        for (GuardData guardData : guards) {
+            if (guardData.getMethodName().equals(name)) {
+                foundGuards.add(guardData);
+            }
+        }
+        for (GuardData guardData : getTypeSystem().getGuards()) {
+            if (guardData.getMethodName().equals(name)) {
+                foundGuards.add(guardData);
+            }
+        }
+        return foundGuards;
+    }
+
+
+    void setGuards(GuardData[] guards) {
+        this.guards = guards;
+    }
+
+    void setSpecification(MethodSpec specification) {
+        this.specification = specification;
+    }
+
+    void setGenericSpecialization(SpecializationData genericSpecialization) {
+        this.genericSpecialization = genericSpecialization;
+    }
+
+    void setSpecializations(SpecializationData[] specializations) {
+        this.specializations = specializations;
+        for (SpecializationData specialization : specializations) {
+            specialization.setOperation(this);
+        }
+    }
+
+    void setSpecializationListeners(TemplateMethod[] specializationListeners) {
+        this.specializationListeners = specializationListeners;
+    }
+
+    public String[] getValues() {
+        return values;
+    }
+
+    public OperationFieldData[] getOperationFields() {
+        return operationFields;
+    }
+
+    public String[] getShortCircuitValues() {
+        return shortCircuitValues;
+    }
+
+    public TypeSystemData getTypeSystem() {
+        return typeSystem;
+    }
+
+    public TypeMirror getNodeType() {
+        return nodeType;
+    }
+
+    public SpecializationData[] getSpecializations() {
+        return specializations;
+    }
+
+    public SpecializationData getGenericSpecialization() {
+        return genericSpecialization;
+    }
+
+    public OperationFieldData[] getConstructorFields() {
+        return constructorFields;
+    }
+
+    public OperationFieldData[] getSuperFields() {
+        return superFields;
+    }
+
+    public MethodSpec getSpecification() {
+        return specification;
+    }
+
+    public SpecializationData[] getAllMethods() {
+        return specializations;
+    }
+
+    public boolean needsRewrites() {
+        boolean needsRewrites = getValues().length > 0 || getShortCircuitValues().length > 0;
+        needsRewrites &= specializations.length >= 2;
+        return needsRewrites;
+    }
+
+    public TemplateMethod[] getSpecializationListeners() {
+        return specializationListeners;
+    }
+
+    public GuardData[] getGuards() {
+        return guards;
+    }
+
+    public SpecializationData findUniqueSpecialization(TypeData type) {
+        SpecializationData result = null;
+        for (SpecializationData specialization : specializations) {
+            if (specialization.getReturnType().getActualTypeData(getTypeSystem()) == type) {
+                if (result != null) {
+                    // Result not unique;
+                    return null;
+                }
+                result = specialization;
+            }
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationFieldData.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.operation;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.*;
+
+public class OperationFieldData {
+
+    private final String name;
+    private final TypeMirror javaClass;
+
+    public OperationFieldData(String name, TypeMirror javaClass) {
+        this.name = name;
+        this.javaClass = javaClass;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public TypeMirror getJavaClass() {
+        return javaClass;
+    }
+
+    @Override
+    public String toString() {
+        return Utils.getSimpleName(javaClass);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationMethodParser.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.operation;
+
+import java.util.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
+
+
+public abstract class OperationMethodParser<E extends TemplateMethod> extends TemplateMethodParser<E>{
+
+    private final OperationData operation;
+
+    public OperationMethodParser(ProcessorContext context, OperationData operation) {
+        super(context);
+        this.operation = operation;
+    }
+
+    public OperationData getOperation() {
+        return operation;
+    }
+
+    protected ParameterSpec createValueParameterSpec(String valueName) {
+        return new ParameterSpec(valueName, operation.getTypeSystem(),
+                        Kind.EXECUTE, false, Cardinality.ONE);
+    }
+
+    protected ParameterSpec createReturnParameterSpec() {
+        return createValueParameterSpec("operation");
+    }
+
+    protected final MethodSpec createDefaultMethodSpec(String shortCircuitName) {
+        List<ParameterSpec> defaultParameters = new ArrayList<>();
+        ParameterSpec frameSpec = new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), Kind.SIGNATURE, true);
+        defaultParameters.add(frameSpec);
+
+        for (String valueName : operation.getValues()) {
+            defaultParameters.add(createValueParameterSpec(valueName));
+        }
+
+        for (String valueName : operation.getShortCircuitValues()) {
+            if (shortCircuitName != null && valueName.equals(shortCircuitName)) {
+                break;
+            }
+
+            defaultParameters.add(new ParameterSpec(shortCircuitValueName(valueName),
+                            getContext().getType(boolean.class), Kind.SHORT_CIRCUIT, false));
+
+            defaultParameters.add(createValueParameterSpec(valueName));
+        }
+
+        for (OperationFieldData field : operation.getSuperFields()) {
+            defaultParameters.add(new ParameterSpec(field.getName(), field.getJavaClass(), Kind.SUPER_ATTRIBUTE, true));
+        }
+
+        for (OperationFieldData field : operation.getOperationFields()) {
+            defaultParameters.add(new ParameterSpec(field.getName(), field.getJavaClass(), Kind.ATTRIBUTE, false));
+        }
+
+        return new MethodSpec(createReturnParameterSpec(), defaultParameters);
+    }
+
+    private static String shortCircuitValueName(String valueName) {
+        return "has" + Utils.firstLetterUpperCase(valueName) + "Value";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationParser.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,569 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.operation;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.ast.*;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
+import com.oracle.truffle.codegen.processor.typesystem.*;
+
+public class OperationParser extends TemplateParser<OperationData> {
+
+    public OperationParser(ProcessorContext c) {
+        super(c);
+    }
+
+    @Override
+    public Class< ? extends Annotation> getAnnotationType() {
+        return com.oracle.truffle.api.codegen.Operation.class;
+    }
+
+    @Override
+    protected OperationData parse(Element element, AnnotationMirror templateTypeAnnotation) {
+        TypeElement templateType = (TypeElement) element;
+
+        if (!verifyTemplateType(templateType, templateTypeAnnotation)) {
+            return null;
+        }
+
+        TypeMirror typeSystemMirror = Utils.getAnnotationValueType(templateTypeAnnotation, "typeSystem");
+        final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSystemMirror, true);
+        if (typeSystem == null) {
+            log.error(templateType, templateTypeAnnotation, "Type system '%s' is invalid.", Utils.getQualifiedName(typeSystemMirror));
+            return null;
+        }
+
+        TypeMirror nodeType = Utils.getAnnotationValueType(templateTypeAnnotation, "baseClass");
+        if (Utils.typeEquals(nodeType, context.getTruffleTypes().getNode())) {
+            nodeType = typeSystem.getNodeType();
+        }
+
+        if (!Utils.isAssignable(nodeType, typeSystem.getNodeType())) {
+            log.error(templateType, templateTypeAnnotation,
+                            Utils.getAnnotationValue(templateTypeAnnotation, "baseClass"),
+                            "The baseClass does not extend the base class of the type system '%s'.", Utils.getQualifiedName(typeSystem.getNodeType()));
+            return null;
+        }
+
+        for (VariableElement field : ElementFilter.fieldsIn(templateType.getEnclosedElements())) {
+            if (!field.getModifiers().contains(Modifier.STATIC)
+                            && !field.getModifiers().contains(Modifier.FINAL)) {
+                log.error(field, "Field must be final.");
+                return null;
+            }
+        }
+
+
+        List<String> valueNames = Utils.getAnnotationValueList(templateTypeAnnotation, "values");
+        List<String> shortCircuitNames = Utils.getAnnotationValueList(templateTypeAnnotation, "shortCircuitValues");
+
+        List<String> names = new ArrayList<>();
+        names.addAll(valueNames);
+        names.addAll(shortCircuitNames);
+
+        List<AnnotationMirror> fieldAnnotations = Collections.emptyList(); // call collectionAnnotations instead if you want OperationField support enabled.
+        List<OperationFieldData> fields = new ArrayList<>();
+        for (AnnotationMirror fieldMirror : fieldAnnotations) {
+            String name = Utils.getAnnotationValueString(fieldMirror, "name");
+            TypeMirror javaClass = Utils.getAnnotationValueType(fieldMirror, "javaClass");
+            fields.add(new OperationFieldData(name, javaClass));
+            names.add(name);
+        }
+
+        List<OperationFieldData> constructorFields = parseConstructorFields(templateType, true);
+        if (constructorFields == null) {
+            return null;
+        }
+
+        List<OperationFieldData> superConstructorFields = parseConstructorFields(Utils.fromTypeMirror(nodeType), false);
+        if (superConstructorFields == null) {
+            return null;
+        }
+
+        List<OperationFieldData> protectedSuperFields = parseProtectedFields(Utils.fromTypeMirror(nodeType));
+        if (protectedSuperFields == null) {
+            return null;
+        }
+
+        List<OperationFieldData> matchedSuperFields = matchFields(superConstructorFields, protectedSuperFields);
+        if (matchedSuperFields == null) {
+            log.error(templateType, templateTypeAnnotation, Utils.getAnnotationValue(templateTypeAnnotation, "baseClass"),
+                            "The signature of the protected fields (%s) and the first constructor(%s) in %s does not match.",
+                            protectedSuperFields.toString(),
+                            superConstructorFields.toString(),
+                            Utils.getQualifiedName(nodeType));
+            return null;
+        }
+
+        for (OperationFieldData field : constructorFields) {
+            names.add(field.getName());
+        }
+
+        for (OperationFieldData field : matchedSuperFields) {
+            names.add(field.getName());
+        }
+
+        if (!verifyNames(templateType, templateTypeAnnotation, names)) {
+            return null;
+        }
+
+        OperationData operationData = new OperationData(templateType, templateTypeAnnotation, typeSystem, nodeType,
+                        valueNames.toArray(new String[valueNames.size()]),
+                        shortCircuitNames.toArray(new String[shortCircuitNames.size()]),
+                        fields.toArray(new OperationFieldData[fields.size()]),
+                        constructorFields.toArray(new OperationFieldData[constructorFields.size()]),
+                        matchedSuperFields.toArray(new OperationFieldData[matchedSuperFields.size()]));
+
+        if (!verifyExclusiveMethodAnnotation(templateType,
+                        Specialization.class, Generic.class, SpecializationListener.class, ShortCircuit.class, GuardCheck.class)) {
+            return noFactory(operationData);
+        }
+
+        operationData.setExtensionElements(getExtensionParser().parseAll(templateType));
+
+        List<SpecializationData> genericSpecializations = parseMethods(operationData, new GenericParser(context, operationData));
+        List<GuardData> guards = parseMethods(operationData, new GuardParser(context, operationData.getTypeSystem(), operationData));
+        operationData.setGuards(guards.toArray(new GuardData[guards.size()]));
+
+        SpecializationParser specializationParser = new SpecializationParser(context, operationData);
+        operationData.setSpecification(specializationParser.getSpecification());
+        List<SpecializationData> specializations = parseMethods(operationData, specializationParser);
+        List<ShortCircuitData> shortCircuits = parseMethods(operationData, new ShortCircuitParser(context, operationData));
+        List<TemplateMethod> listeners = parseMethods(operationData, new SpecializationListenerParser(context, operationData));
+
+        if (specializations == null || genericSpecializations == null || shortCircuits == null  || listeners == null || guards == null) {
+            return noFactory(operationData);
+        }
+
+
+        SpecializationData genericSpecialization = null;
+        if (genericSpecializations.size() > 1) {
+            for (SpecializationData generic : genericSpecializations) {
+                log.error(generic.getMethod(), "Only one method with @%s is allowed per operation.", Generic.class.getSimpleName());
+            }
+            return noFactory(operationData);
+        } else if (genericSpecializations.size() == 1) {
+            genericSpecialization = genericSpecializations.get(0);
+        }
+
+        if (specializations.size() > 1 && genericSpecialization == null) {
+            log.error(templateType, "Need a @%s method.", Generic.class.getSimpleName());
+            return noFactory(operationData);
+        }
+
+        Collections.sort(specializations, new Comparator<SpecializationData>() {
+            @Override
+            public int compare(SpecializationData o1, SpecializationData o2) {
+                return compareSpecialization(typeSystem, o1, o2);
+            }
+        });
+
+        List<SpecializationData> allSpecializations = new ArrayList<>(specializations);
+        if (genericSpecialization != null) {
+            allSpecializations.add(genericSpecialization);
+            TemplateMethod uninializedMethod = new TemplateMethod(genericSpecialization.getSpecification(), new CodeExecutableElement(context.getType(void.class), "doUninialized"),
+                            genericSpecialization.getMarkerAnnotation(), genericSpecialization.getReturnType(), genericSpecialization.getParameters());
+            allSpecializations.add(0, new SpecializationData(uninializedMethod, false, true));
+        }
+
+        // verify order is not ambiguous
+        verifySpecializationOrder(typeSystem, specializations);
+
+        operationData.setGenericSpecialization(genericSpecialization);
+        operationData.setSpecializations(allSpecializations.toArray(new SpecializationData[allSpecializations.size()]));
+        operationData.setSpecializationListeners(listeners.toArray(new TemplateMethod[listeners.size()]));
+
+        if (!assignShortCircuitsToSpecializations(operationData, allSpecializations, shortCircuits)) {
+            return null;
+        }
+
+        if (!verifyNamingConvention(specializations, "do")) {
+            return noFactory(operationData);
+        }
+
+        if (!verifyNamesUnique(specializations)) {
+            return noFactory(operationData);
+        }
+
+        if (!verifyNamingConvention(shortCircuits, "needs")) {
+            return noFactory(operationData);
+        }
+
+        if (!verifySpecializationThrows(typeSystem, specializations)) {
+            return noFactory(operationData);
+        }
+
+        return operationData;
+    }
+
+    private static List<OperationFieldData> matchFields(List<OperationFieldData> params,
+                    List<OperationFieldData> fields) {
+
+        if (params.size() != fields.size()) {
+            return null;
+        }
+
+        List<OperationFieldData> matchedFields = new ArrayList<>();
+        for (int i = 0; i < params.size(); i++) {
+            OperationFieldData param = params.get(i);
+            OperationFieldData field = fields.get(i);
+            if (!Utils.typeEquals(param.getJavaClass(), field.getJavaClass())) {
+                return null;
+            }
+            matchedFields.add(new OperationFieldData(field.getName(), param.getJavaClass()));
+        }
+
+        return matchedFields;
+    }
+
+    private static List<OperationFieldData> parseProtectedFields(Element element) {
+        List<OperationFieldData> opFields = new ArrayList<>();
+        List<VariableElement> fields = ElementFilter.fieldsIn(element.getEnclosedElements());
+        for (VariableElement var : fields) {
+            if (var.getModifiers().contains(Modifier.STATIC)) {
+                continue;
+            }
+
+            if (var.getModifiers().contains(Modifier.PROTECTED)) {
+                opFields.add(new OperationFieldData(var.getSimpleName().toString(), var.asType()));
+            }
+        }
+        return opFields;
+
+    }
+
+    private List<OperationFieldData> parseConstructorFields(Element element, boolean failOnMultipleConstructors) {
+        if (element == null) {
+            return Collections.emptyList();
+        }
+
+        List<ExecutableElement> constructors = ElementFilter.constructorsIn(element.getEnclosedElements());
+        ExecutableElement constructor = null;
+        if (constructors.size() > 1) {
+            if (failOnMultipleConstructors) {
+                for (ExecutableElement c : constructors) {
+                    log.error(c, "The Operation annotated class must not define multiple constructors.");
+                }
+                return null;
+            } else {
+                // take first constructor
+                constructor = constructors.get(0);
+            }
+        } else if (constructors.size() == 1) {
+            constructor = constructors.get(0);
+        }
+
+        List<OperationFieldData> constructorFields = new ArrayList<>();
+        if (constructor != null) {
+            for (VariableElement var : constructor.getParameters()) {
+                constructorFields.add(new OperationFieldData(var.getSimpleName().toString(), var.asType()));
+            }
+        }
+        return constructorFields;
+    }
+
+    private static OperationData noFactory(OperationData data) {
+        data.generateFactory = false;
+        return data;
+    }
+
+    private boolean verifySpecializationThrows(TypeSystemData typeSystem, List<SpecializationData> specializations) {
+        Map<String, SpecializationData> specializationMap = new HashMap<>();
+        for (SpecializationData spec : specializations) {
+            specializationMap.put(spec.getMethodName(), spec);
+        }
+        boolean valid = true;
+        for (SpecializationData sourceSpecialization : specializations) {
+            if (sourceSpecialization.getExceptions() != null) {
+                for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) {
+                    SpecializationData targetSpecialization = specializationMap.get(throwsData.getTransitionToName());
+                    AnnotationValue value = Utils.getAnnotationValue(throwsData.getAnnotationMirror(), "transitionTo");
+                    if (targetSpecialization == null) {
+                        log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), value,
+                                        "Specialization with name '%s' not found.", throwsData.getTransitionToName());
+                        valid = false;
+                    } else if (compareSpecialization(typeSystem, sourceSpecialization, targetSpecialization) >= 0) {
+                        log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), value,
+                                        "The order of the target specializalization must be higher than the source specialization.", throwsData.getTransitionToName());
+                        valid = false;
+                    }
+
+                    for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) {
+                        if (otherThrowsData != throwsData
+                                        && Utils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) {
+                            AnnotationValue javaClassValue = Utils.getAnnotationValue(throwsData.getAnnotationMirror(), "javaClass");
+                            log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), javaClassValue,
+                                            "Duplicate exception type.", throwsData.getTransitionToName());
+                            valid = false;
+                        }
+                    }
+                }
+            }
+        }
+        return valid;
+    }
+
+
+    private boolean assignShortCircuitsToSpecializations(OperationData operation,
+                    List<SpecializationData> specializations,
+                    List<ShortCircuitData> shortCircuits) {
+
+        Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(shortCircuits);
+
+        boolean valid = true;
+
+        for (String valueName : operation.getShortCircuitValues()) {
+            List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
+
+            if (availableCircuits == null || availableCircuits.isEmpty()) {
+                log.error(operation.getTemplateType(), operation.getTemplateTypeAnnotation(),
+                                "@%s method for short cut value '%s' required.",
+                                ShortCircuit.class.getSimpleName(), valueName);
+                valid = false;
+                continue;
+            }
+
+
+            boolean sameMethodName = true;
+            String methodName = availableCircuits.get(0).getMethodName();
+            for (ShortCircuitData circuit : availableCircuits) {
+                if (!circuit.getMethodName().equals(methodName)) {
+                    sameMethodName = false;
+                }
+            }
+
+            if (!sameMethodName) {
+                for (ShortCircuitData circuit : availableCircuits) {
+                    log.error(circuit.getMethod(), circuit.getMarkerAnnotation(), "All short circuits for short cut value '%s' must have the same method name.", valueName);
+                }
+                valid = false;
+                continue;
+            }
+
+            ShortCircuitData genericCircuit = null;
+            for (ShortCircuitData circuit : availableCircuits) {
+                if (isGenericShortCutMethod(circuit, operation.getTypeSystem().getGenericType())) {
+                    genericCircuit = circuit;
+                    break;
+                }
+            }
+
+            if (genericCircuit == null) {
+                log.error(operation.getTemplateType(), operation.getTemplateTypeAnnotation(),
+                                "No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
+                valid = false;
+                continue;
+            }
+
+            for (ShortCircuitData circuit : availableCircuits) {
+                if (circuit != genericCircuit) {
+                    circuit.setGenericShortCircuitMethod(genericCircuit);
+                }
+            }
+        }
+
+        if (!valid) {
+            return valid;
+        }
+
+        for (SpecializationData specialization : specializations) {
+            ShortCircuitData[] assignedShortCuts = new ShortCircuitData[operation.getShortCircuitValues().length];
+
+            for (int i = 0; i < operation.getShortCircuitValues().length; i++) {
+                List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(operation.getShortCircuitValues()[i]);
+
+                ShortCircuitData genericShortCircuit = null;
+                for (ShortCircuitData circuit : availableShortCuts) {
+                    if (circuit.isGeneric()) {
+                        genericShortCircuit = circuit;
+                    } else if (circuit.isCompatibleTo(specialization)) {
+                        assignedShortCuts[i] = circuit;
+                    }
+                }
+
+                if (assignedShortCuts[i] == null) {
+                    assignedShortCuts[i] = genericShortCircuit;
+                }
+            }
+            specialization.setShortCircuits(assignedShortCuts);
+        }
+        return true;
+    }
+
+    private static boolean isGenericShortCutMethod(TemplateMethod method, TypeMirror genericType) {
+        for (ActualParameter parameter : method.getParameters()) {
+            if (parameter.getSpecification().getKind() == Kind.EXECUTE) {
+                if (!Utils.typeEquals(genericType, parameter.getActualType())) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private static Map<String, List<ShortCircuitData>> groupShortCircuits(List<ShortCircuitData> shortCircuits) {
+        Map<String, List<ShortCircuitData>> group = new HashMap<>();
+        for (ShortCircuitData shortCircuit : shortCircuits) {
+            List<ShortCircuitData> circuits = group.get(shortCircuit.getValueName());
+            if (circuits == null) {
+                circuits = new ArrayList<>();
+                group.put(shortCircuit.getValueName(), circuits);
+            }
+            circuits.add(shortCircuit);
+        }
+        return group;
+    }
+
+    private boolean verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) {
+        boolean valid = true;
+        for (int i = 0; i < methods.size(); i++) {
+            TemplateMethod m1 = methods.get(i);
+            if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
+                log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Naming convention: method name must start with '%s'.", prefix);
+                valid = false;
+            }
+        }
+        return valid;
+    }
+
+    private boolean verifyNamesUnique(List<? extends TemplateMethod> methods) {
+        boolean valid = true;
+        for (int i = 0; i < methods.size(); i++) {
+            TemplateMethod m1 = methods.get(i);
+            for (int j = i + 1; j < methods.size(); j++) {
+                TemplateMethod m2 = methods.get(j);
+
+                if (m1.getMethodName().equalsIgnoreCase(m2.getMethodName())) {
+                    log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Method name '%s' used multiple times", m1.getMethodName());
+                    log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Method name '%s' used multiple times", m1.getMethodName());
+                    return false;
+                }
+            }
+        }
+        return valid;
+    }
+
+    private boolean verifySpecializationOrder(TypeSystemData typeSystem, List<SpecializationData> specializations) {
+        for (int i = 0; i < specializations.size(); i++) {
+            SpecializationData m1 = specializations.get(i);
+            for (int j = i + 1; j < specializations.size(); j++) {
+                SpecializationData m2 = specializations.get(j);
+                int inferredOrder = compareSpecializationWithoutOrder(typeSystem, m1, m2);
+
+                if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
+                    int specOrder = m1.getOrder() - m2.getOrder();
+                    if (specOrder == 0) {
+                        log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Order value %d used multiple times", m1.getOrder());
+                        log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Order value %d used multiple times", m1.getOrder());
+                        return false;
+                    } else if ((specOrder < 0 && inferredOrder > 0) || (specOrder > 0 && inferredOrder < 0)) {
+                        log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
+                        log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder());
+                        return false;
+                    }
+                } else if (inferredOrder == 0) {
+                    SpecializationData m = (m1.getOrder() == Specialization.DEFAULT_ORDER ? m1 : m2);
+                    log.error(m.getMethod(), m.getMarkerAnnotation(), "Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this.");
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private static int compareSpecialization(TypeSystemData typeSystem, SpecializationData m1, SpecializationData m2) {
+        int result = compareSpecializationWithoutOrder(typeSystem, m1, m2);
+        if (result == 0) {
+            if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
+                return m1.getOrder() - m2.getOrder();
+            }
+        }
+        return result;
+    }
+
+    private static int compareSpecializationWithoutOrder(TypeSystemData typeSystem, SpecializationData m1, SpecializationData m2) {
+        if (m1.getSpecification() != m2.getSpecification()) {
+            throw new UnsupportedOperationException("Cannot compare two specializations with different specifications.");
+        }
+
+        int result = compareActualParameter(typeSystem, m1.getReturnType(), m2.getReturnType());
+
+        for (ParameterSpec spec : m1.getSpecification().getParameters()) {
+            ActualParameter p1 = m1.findParameter(spec);
+            ActualParameter p2 = m2.findParameter(spec);
+
+            if (p1 != null && p2 != null && !Utils.typeEquals(p1.getActualType(), p2.getActualType())) {
+                int typeResult = compareActualParameter(typeSystem, p1, p2);
+                if (result == 0) {
+                    result = typeResult;
+                } else if (Math.signum(result) != Math.signum(typeResult)) {
+                    // We cannot define an order.
+                    return 0;
+                }
+            }
+        }
+        return result;
+    }
+
+    private static int compareActualParameter(TypeSystemData typeSystem, ActualParameter p1, ActualParameter p2) {
+        int index1 = typeSystem.findType(p1.getActualType());
+        int index2 = typeSystem.findType(p2.getActualType());
+
+        assert index1 != index2;
+        assert !(index1 == -1 ^ index2 == -1);
+
+        return index1 - index2;
+    }
+
+    private boolean verifyNames(TypeElement element, AnnotationMirror mirror, List<String> names) {
+        boolean valid = true;
+
+        for (int i = 0; i < names.size(); i++) {
+            String name = names.get(i);
+            if (!JavaName.isValid(name)) {
+                log.error(element, mirror, "Name '%s' is not a valid java identifier.", name);
+                valid = false;
+            } else if (JavaName.isReserved(name)) {
+                log.error(element, mirror, "Name '%s' is a reserved java identifier.", name);
+                valid = false;
+            }
+            for (int j = i + 1; j < names.size(); j++) {
+                String otherName = names.get(j);
+                if (name.equalsIgnoreCase(otherName)) {
+                    log.error(element, mirror, "Name '%s' is not unique.", name);
+                    valid = false;
+                }
+            }
+        }
+        return valid;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/ShortCircuitData.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.codegen.processor.operation;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
+
+
+public class ShortCircuitData extends TemplateMethod {
+
+    private ShortCircuitData genericShortCircuitMethod;
+
+    private final String valueName;
+
+    public ShortCircuitData(TemplateMethod template, String valueName) {
+        super(template);
+        this.valueName = valueName;
+    }
+
+    public String getValueName() {
+        return valueName;
+    }
+
+    public void setGenericShortCircuitMethod(ShortCircuitData genericShortCircuitMethod) {
+        this.genericShortCircuitMethod = genericShortCircuitMethod;
+    }
+
+    public boolean isGeneric() {
+        return genericShortCircuitMethod == null;
+    }
+
+    public ShortCircuitData getGeneric() {
+        if (isGeneric()) {
+            return this;
+        } else {
+            return genericShortCircuitMethod;
+        }
+    }
+
+    public boolean isCompatibleTo(SpecializationData specialization) {
+        if (isGeneric() && specialization.isGeneric()) {
+            return true;
+        }
+
+        for (ActualParameter param : getParameters()) {
+            ParameterSpec paramSpec = param.getSpecification();
+            if (paramSpec.getKind() == Kind.EXECUTE) {
+                ActualParameter specializationParam = specialization.findParameter(paramSpec.getName());
+                if (!Utils.typeEquals(param.getActualType(), specializationParam.getActualType())) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/ShortCircuitParser.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.codegen.processor.operation;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
+
+
+public class ShortCircuitParser extends OperationMethodParser<ShortCircuitData> {
+
+    private final Set<String> shortCircuitValues;
+
+    public ShortCircuitParser(ProcessorContext context, OperationData operation) {
+        super(context, operation);
+        shortCircuitValues = new HashSet<>(Arrays.asList(operation.getShortCircuitValues()));
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        String shortCircuitValue = Utils.getAnnotationValueString(mirror, "value");
+
+        if (!shortCircuitValues.contains(shortCircuitValue)) {
+            getContext().getLog().error(method, mirror, "Invalid short circuit value %s.", shortCircuitValue);
+            return null;
+        }
+
+        return createDefaultMethodSpec(shortCircuitValue);
+    }
+
+    @Override
+    protected ParameterSpec createReturnParameterSpec() {
+        return new ParameterSpec("has", getContext().getType(boolean.class), Kind.SHORT_CIRCUIT, false);
+    }
+
+    @Override
+    public ShortCircuitData create(TemplateMethod method) {
+        String shortCircuitValue = Utils.getAnnotationValueString(method.getMarkerAnnotation(), "value");
+        assert shortCircuitValue != null;
+        assert shortCircuitValues.contains(shortCircuitValue);
+        return new ShortCircuitData(method, shortCircuitValue);
+    }
+
+    @Override
+    public Class< ? extends Annotation> getAnnotationType() {
+        return ShortCircuit.class;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationData.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.operation;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.template.*;
+
+public class SpecializationData extends TemplateMethod {
+
+    private final int order;
+    private final boolean generic;
+    private final boolean uninitialized;
+    private final SpecializationThrowsData[] exceptions;
+    private SpecializationGuardData[] guards;
+    private ShortCircuitData[] shortCircuits;
+
+    private OperationData operation;
+
+    public SpecializationData(TemplateMethod template, int order, SpecializationThrowsData[] exceptions) {
+        super(template.getSpecification(), template.getMethod(), template.getMarkerAnnotation(), template.getReturnType(), template.getParameters());
+        this.order = order;
+        this.generic = false;
+        this.uninitialized = false;
+        this.exceptions = exceptions;
+
+        for (SpecializationThrowsData exception : exceptions) {
+            exception.setSpecialization(this);
+        }
+    }
+
+    public SpecializationData(TemplateMethod template, boolean generic, boolean uninitialized) {
+        super(template.getSpecification(), template.getMethod(), template.getMarkerAnnotation(), template.getReturnType(), template.getParameters());
+        this.order = Specialization.DEFAULT_ORDER;
+        this.generic = generic;
+        this.uninitialized = uninitialized;
+        this.exceptions = new SpecializationThrowsData[0];
+        this.guards = new SpecializationGuardData[0];
+    }
+
+    public void setOperation(OperationData operation) {
+        this.operation = operation;
+    }
+
+    void setGuards(SpecializationGuardData[] guards) {
+        this.guards = guards;
+    }
+
+    public OperationData getOperation() {
+        return operation;
+    }
+
+    public int getOrder() {
+        return order;
+    }
+
+    public boolean isGeneric() {
+        return generic;
+    }
+
+    public boolean isUninitialized() {
+        return uninitialized;
+    }
+
+    public SpecializationThrowsData[] getExceptions() {
+        return exceptions;
+    }
+
+    public SpecializationGuardData[] getGuards() {
+        return guards;
+    }
+
+    public void setShortCircuits(ShortCircuitData[] shortCircuits) {
+        this.shortCircuits = shortCircuits;
+    }
+
+    public ShortCircuitData[] getShortCircuits() {
+        return shortCircuits;
+    }
+
+    public SpecializationData findNextSpecialization() {
+        SpecializationData[] allMethods = operation.getAllMethods();
+        for (int i = 0; i < allMethods.length - 1; i++) {
+            if (allMethods[i] == this) {
+                return allMethods[i + 1];
+            }
+        }
+        throw new IllegalArgumentException();
+    }
+
+    public boolean hasDynamicGuards() {
+        for (SpecializationGuardData guard : getGuards()) {
+            if (guard.isOnExecution()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public ActualParameter getPreviousParam(ActualParameter searchParam) {
+        ActualParameter prev = null;
+        for (ActualParameter param : getParameters()) {
+            if (param == searchParam) {
+                return prev;
+            }
+            prev = param;
+        }
+        return prev;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationGuardData.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.operation;
+
+import com.oracle.truffle.codegen.processor.typesystem.*;
+
+public class SpecializationGuardData {
+
+    private final String guardMethod;
+    private final boolean onSpecialization;
+    private final boolean onExecution;
+
+    private GuardData guardDeclaration;
+
+    public SpecializationGuardData(String guardMethod, boolean onSpecialization, boolean onExecution) {
+        this.guardMethod = guardMethod;
+        this.onSpecialization = onSpecialization;
+        this.onExecution = onExecution;
+    }
+
+    public String getGuardMethod() {
+        return guardMethod;
+    }
+
+    public boolean isOnExecution() {
+        return onExecution;
+    }
+
+    public boolean isOnSpecialization() {
+        return onSpecialization;
+    }
+
+    void setGuardDeclaration(GuardData compatibleGuard) {
+        this.guardDeclaration = compatibleGuard;
+    }
+
+    public GuardData getGuardDeclaration() {
+        return guardDeclaration;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationListenerParser.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.operation;
+
+import java.lang.annotation.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
+
+
+public class SpecializationListenerParser extends OperationMethodParser<TemplateMethod> {
+
+    private final MethodSpec specification;
+
+    public SpecializationListenerParser(ProcessorContext context, OperationData operation) {
+        super(context, operation);
+        this.specification = createDefaultMethodSpec(null);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        return specification;
+    }
+
+    @Override
+    protected ParameterSpec createReturnParameterSpec() {
+        return new ParameterSpec("void", getContext().getType(void.class), Kind.ATTRIBUTE, false);
+    }
+
+    @Override
+    public TemplateMethod create(TemplateMethod method) {
+        return method;
+    }
+
+    @Override
+    public Class< ? extends Annotation> getAnnotationType() {
+        return SpecializationListener.class;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationParser.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.operation;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
+import com.oracle.truffle.codegen.processor.typesystem.*;
+
+
+public class SpecializationParser extends OperationMethodParser<SpecializationData> {
+
+    private final MethodSpec specification;
+
+    public SpecializationParser(ProcessorContext context, OperationData operation) {
+        super(context, operation);
+        this.specification = createDefaultMethodSpec(null);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        return specification;
+    }
+    public MethodSpec getSpecification() {
+        return specification;
+    }
+
+    @Override
+    public SpecializationData create(TemplateMethod method) {
+        return parseSpecialization(method);
+    }
+
+    @Override
+    public Class< ? extends Annotation> getAnnotationType() {
+        return Specialization.class;
+    }
+
+    private SpecializationData parseSpecialization(TemplateMethod template) {
+        int order = Utils.getAnnotationValueInt(template.getMarkerAnnotation(), "order");
+        if (order < 0 && order != Specialization.DEFAULT_ORDER) {
+            getContext().getLog().error(template.getMethod(), template.getMarkerAnnotation(), "Invalid order attribute %d. The value must be >= 0 or the default value.");
+            return null;
+        }
+
+        List<AnnotationMirror> exceptionDefs = Utils.collectAnnotations(getContext(), template.getMarkerAnnotation(), "exceptions", template.getMethod(), SpecializationThrows.class);
+        SpecializationThrowsData[] exceptionData = new SpecializationThrowsData[exceptionDefs.size()];
+        for (int i = 0; i < exceptionData.length; i++) {
+            AnnotationMirror mirror = exceptionDefs.get(i);
+            TypeMirror javaClass = Utils.getAnnotationValueType(mirror, "javaClass");
+            String transitionTo = Utils.getAnnotationValueString(mirror, "transitionTo");
+            exceptionData[i] = new SpecializationThrowsData(mirror, javaClass, transitionTo);
+
+            if (!Utils.canThrowType(template.getMethod().getThrownTypes(), javaClass)) {
+                getContext().getLog().error(template.getMethod(), "Method must specify a throws clause with the exception type '%s'.", Utils.getQualifiedName(javaClass));
+                return null;
+            }
+        }
+
+        Arrays.sort(exceptionData, new Comparator<SpecializationThrowsData>() {
+            @Override
+            public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) {
+                return Utils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass());
+            }
+        });
+        SpecializationData specialization = new SpecializationData(template, order, exceptionData);
+
+        boolean valid = true;
+        List<AnnotationMirror> guardDefs = Utils.collectAnnotations(getContext(), template.getMarkerAnnotation(), "guards", template.getMethod(), SpecializationGuard.class);
+        SpecializationGuardData[] guardData = new SpecializationGuardData[guardDefs.size()];
+        for (int i = 0; i < guardData.length; i++) {
+            AnnotationMirror guardMirror = guardDefs.get(i);
+            String guardMethod = Utils.getAnnotationValueString(guardMirror, "methodName");
+            boolean onSpecialization = Utils.getAnnotationValueBoolean(guardMirror, "onSpecialization");
+            boolean onExecution = Utils.getAnnotationValueBoolean(guardMirror, "onExecution");
+
+            if (!onSpecialization && !onExecution) {
+                String message = "Either onSpecialization, onExecution or both must be enabled.";
+                getContext().getLog().error(template.getMethod(), guardMirror, message);
+                valid = false;
+                continue;
+            }
+
+            guardData[i] = new SpecializationGuardData(guardMethod, onSpecialization, onExecution);
+
+            GuardData compatibleGuard = matchSpecializationGuard(guardMirror, specialization, guardData[i]);
+            if (compatibleGuard != null) {
+                guardData[i].setGuardDeclaration(compatibleGuard);
+            } else {
+                valid = false;
+            }
+        }
+
+        if (!valid) {
+            return null;
+        }
+
+        specialization.setGuards(guardData);
+
+        return specialization;
+    }
+
+    private GuardData matchSpecializationGuard(AnnotationMirror mirror, SpecializationData specialization, SpecializationGuardData specializationGuard)  {
+        List<GuardData> foundGuards = getOperation().findGuards(specializationGuard.getGuardMethod());
+        GuardData compatibleGuard = null;
+        for (GuardData guardData : foundGuards) {
+            if (isGuardCompatible(specialization, guardData)) {
+                compatibleGuard = guardData;
+                break;
+            }
+        }
+
+        if (compatibleGuard == null) {
+            ParameterSpec returnTypeSpec = new ParameterSpec("returnValue", getContext().getType(boolean.class), Kind.ATTRIBUTE, false);
+            List<ParameterSpec> expectedParameterSpecs = new ArrayList<>();
+
+            for (ActualParameter param : filterGuardParameters(specialization)) {
+                ParameterSpec spec = param.getSpecification();
+                expectedParameterSpecs.add(new ParameterSpec(spec.getName(), param.getActualType(), Kind.ATTRIBUTE, false));
+            }
+            String expectedSignature = TemplateMethodParser.createExpectedSignature(specializationGuard.getGuardMethod(), returnTypeSpec, expectedParameterSpecs);
+            AnnotationValue value = Utils.getAnnotationValue(mirror, "methodName");
+            getContext().getLog().error(specialization.getMethod(), mirror, value, "No guard with signature '%s' found in type system.", expectedSignature);
+            return null;
+        }
+
+        return compatibleGuard;
+    }
+
+    private static boolean isGuardCompatible(SpecializationData specialization, GuardData guard) {
+        Iterator<ActualParameter> guardParameters = Arrays.asList(guard.getParameters()).iterator();
+        for (ActualParameter param : filterGuardParameters(specialization)) {
+            if (!guardParameters.hasNext()) {
+                return false;
+            }
+            ActualParameter guardParam = guardParameters.next();
+            if (!Utils.typeEquals(guardParam.getActualType(), param.getActualType())) {
+                return false;
+            }
+        }
+        if (guardParameters.hasNext()) {
+            return false;
+        }
+        return true;
+    }
+
+    private static List<ActualParameter> filterGuardParameters(SpecializationData specialization) {
+        List<ActualParameter> parameters = new ArrayList<>();
+        for (ActualParameter param : specialization.getParameters()) {
+            if (param.getSpecification().getKind() != Kind.EXECUTE
+                            && param.getSpecification().getKind() != Kind.SHORT_CIRCUIT) {
+                continue;
+            }
+            parameters.add(param);
+        }
+        return parameters;
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationThrowsData.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.operation;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class SpecializationThrowsData {
+
+    private final AnnotationMirror annotationMirror;
+    private final TypeMirror javaClass;
+    private final String transitionTo;
+    private SpecializationData specialization;
+
+    public SpecializationThrowsData(AnnotationMirror annotationMirror, TypeMirror javaClass, String transitionTo) {
+        this.annotationMirror = annotationMirror;
+        this.javaClass = javaClass;
+        this.transitionTo = transitionTo;
+    }
+
+
+    void setSpecialization(SpecializationData specialization) {
+        this.specialization = specialization;
+    }
+
+    public TypeMirror getJavaClass() {
+        return javaClass;
+    }
+
+    public SpecializationData getSpecialization() {
+        return specialization;
+    }
+
+    public AnnotationMirror getAnnotationMirror() {
+        return annotationMirror;
+    }
+
+    public String getTransitionToName() {
+        return transitionTo;
+    }
+
+    public SpecializationData getTransitionTo() {
+        for (SpecializationData s : specialization.getOperation().getAllMethods()) {
+            if (s.getMethodName().equals(transitionTo)) {
+                return s;
+            }
+        }
+        throw new IllegalArgumentException();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.template;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.typesystem.*;
+
+public class ActualParameter {
+
+    private final ParameterSpec specification;
+    private final TypeMirror actualType;
+
+    public ActualParameter(ParameterSpec specification, TypeMirror actualType) {
+        this.specification = specification;
+        this.actualType = actualType;
+    }
+
+    public ParameterSpec getSpecification() {
+        return specification;
+    }
+
+    public TypeMirror getActualType() {
+        return actualType;
+    }
+
+    public TypeData getActualTypeData(TypeSystemData typeSystem) {
+        return typeSystem.getTypes()[typeSystem.findType(actualType)];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.template;
+
+import static com.oracle.truffle.codegen.processor.Utils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.ast.*;
+
+public abstract class ClassElementFactory<M> extends CodeElementFactory<M> {
+
+    public ClassElementFactory(ProcessorContext context) {
+        super(context);
+    }
+
+    @Override
+    protected abstract CodeTypeElement create(M m);
+
+    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 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()));
+        clazz.addAnnotationMirror(generatedByAnnotation);
+
+        context.registerType(model.getTemplateType(), clazz.asType());
+
+        return clazz;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CodeElementFactory.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.template;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.ast.*;
+
+public abstract class CodeElementFactory<M> {
+
+    protected final ProcessorContext context;
+    private M model;
+
+    private CodeElement<? super Element> element;
+
+    public CodeElementFactory(ProcessorContext context) {
+        this.context = context;
+    }
+
+    protected abstract CodeElement<?> create(M m);
+
+    @SuppressWarnings("unused")
+    protected void createChildren(M m) { }
+
+    @SuppressWarnings("unchecked")
+    public final CodeElement<?> process(M m) {
+        model = m;
+        element = (CodeElement<? super Element>) create(model);
+        if (element != null) {
+            createChildren(model);
+        }
+        return element;
+    }
+
+    public CodeElement getElement() {
+        return element;
+    }
+
+    protected <MO, K extends Element> void add(CodeElementFactory<MO> factory, MO m) {
+        this.element.add(factory.process(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.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CompilationUnitFactory.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.template;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.ast.*;
+
+public abstract class CompilationUnitFactory<M> extends CodeElementFactory<M> {
+
+    public CompilationUnitFactory(ProcessorContext context) {
+        super(context);
+    }
+
+    @Override
+    public final CodeCompilationUnit create(M m) {
+        return new CodeCompilationUnit();
+    }
+
+    @Override
+    protected abstract void createChildren(M m);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/JavaName.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.template;
+
+import java.util.*;
+import java.util.regex.*;
+
+
+public final class JavaName {
+
+    private static final String[] RESERVED_NAMES = new String[]{"abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package", "synchronized", "boolean", "do", "if",
+        "private", "this", "break", "double", "implements", "protected", "throw", "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient",
+        "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", "finally", "long", "strictfp", "volatile", "const", "float", "native", "super",
+        "while"};
+
+    private static final Set<String> RESERVED_NAMES_SET = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(RESERVED_NAMES)));
+
+    private static final Pattern VALID_JAVA_NAME_PATTERN = Pattern.compile("[_a-zA-z][_a-zA-Z0-9]*");
+
+    private JavaName() {
+        super();
+    }
+
+    public static boolean isReserved(String name) {
+        return RESERVED_NAMES_SET.contains(name);
+    }
+
+    public static boolean isValid(String typeName) {
+        return VALID_JAVA_NAME_PATTERN.matcher(typeName).matches();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.template;
+
+import java.util.*;
+
+public class MethodSpec {
+
+    private final ParameterSpec returnType;
+    private final List<ParameterSpec> parameters;
+
+    public MethodSpec(ParameterSpec returnType, List<ParameterSpec> parameters) {
+        this.returnType = returnType;
+        this.parameters = parameters;
+    }
+
+    public ParameterSpec getReturnType() {
+        return returnType;
+    }
+
+    public List<ParameterSpec> getParameters() {
+        return parameters;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.template;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.typesystem.*;
+
+public class ParameterSpec {
+
+    public enum Kind {
+        EXECUTE, SIGNATURE, SUPER_ATTRIBUTE, ATTRIBUTE, CONSTRUCTOR_FIELD, SHORT_CIRCUIT
+    }
+
+    public enum Cardinality {
+        ONE, MULTIPLE;
+    }
+
+    private final String name;
+    private final TypeMirror[] allowedTypes;
+    private final TypeMirror valueType;
+    private final Kind kind;
+    private final boolean optional;
+    private final Cardinality cardinality;
+
+    public ParameterSpec(String name, TypeMirror[] allowedTypes, TypeMirror valueType, Kind kind, boolean optional, Cardinality cardinality) {
+        this.valueType = valueType;
+        this.allowedTypes = allowedTypes;
+        this.name = name;
+        this.kind = kind;
+        this.optional = optional;
+        this.cardinality = cardinality;
+    }
+
+    public ParameterSpec(String name, TypeMirror singleFixedType, Kind kind, boolean optional) {
+        this(name, new TypeMirror[]{singleFixedType}, singleFixedType, kind, optional, Cardinality.ONE);
+    }
+
+    public ParameterSpec(String name, TypeSystemData typeSystem, Kind kind, boolean optional, Cardinality cardinality) {
+        this(name, typeSystem.getPrimitiveTypeMirrors(), typeSystem.getGenericType(), kind, optional, cardinality);
+    }
+
+    public final String getName() {
+        return name;
+    }
+
+    public Kind getKind() {
+        return kind;
+    }
+
+    public final boolean isOptional() {
+        return optional;
+    }
+
+    public final Cardinality getCardinality() {
+        return cardinality;
+    }
+
+    public TypeMirror[] getAllowedTypes() {
+        return allowedTypes;
+    }
+
+    public boolean matches(TypeMirror actualType) {
+        for (int i = 0; i < allowedTypes.length; i++) {
+            TypeMirror mirror = allowedTypes[i];
+            if (Utils.typeEquals(actualType, mirror)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public TypeMirror getValueType() {
+        return valueType;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/Template.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.template;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.api.element.*;
+
+public abstract class Template {
+
+    private final TypeElement templateType;
+    private final AnnotationMirror annotation;
+
+    private List<? extends WritableElement> extensionElements;
+
+    public Template(TypeElement templateType, AnnotationMirror annotation) {
+        this.templateType = templateType;
+        this.annotation = annotation;
+    }
+
+    public TypeElement getTemplateType() {
+        return templateType;
+    }
+
+    public AnnotationMirror getTemplateTypeAnnotation() {
+        return annotation;
+    }
+
+    public List< ? extends WritableElement> getExtensionElements() {
+        return extensionElements;
+    }
+
+    public void setExtensionElements(List< ? extends WritableElement> extensionMethods) {
+        this.extensionElements = extensionMethods;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + Utils.getSimpleName(getTemplateType()) + "]";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.template;
+
+import javax.lang.model.element.*;
+
+public class TemplateMethod {
+
+    private final MethodSpec specification;
+    private final ExecutableElement method;
+    private final AnnotationMirror markerAnnotation;
+    private final ActualParameter returnType;
+    private final ActualParameter[] parameters;
+
+    public TemplateMethod(MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType, ActualParameter[] parameters) {
+        this.specification = specification;
+        this.method = method;
+        this.markerAnnotation = markerAnnotation;
+        this.returnType = returnType;
+        this.parameters = parameters;
+    }
+
+    public TemplateMethod(TemplateMethod method) {
+        this.specification = method.specification;
+        this.method = method.method;
+        this.markerAnnotation = method.markerAnnotation;
+        this.returnType = method.returnType;
+        this.parameters = method.parameters;
+    }
+
+
+    public MethodSpec getSpecification() {
+        return specification;
+    }
+
+    public ActualParameter getReturnType() {
+        return returnType;
+    }
+
+    public ActualParameter[] getParameters() {
+        return parameters;
+    }
+
+    public ActualParameter findParameter(String valueName) {
+        for (ActualParameter param : getParameters()) {
+            if (param.getSpecification().getName().equals(valueName)) {
+                return param;
+            }
+        }
+        return null;
+    }
+
+    public ActualParameter findParameter(ParameterSpec spec) {
+        for (ActualParameter param : getParameters()) {
+            if (param.getSpecification() == spec) {
+                return param;
+            }
+        }
+        return null;
+    }
+
+    public ExecutableElement getMethod() {
+        return method;
+    }
+
+    public String getMethodName() {
+        return getMethod().getSimpleName().toString();
+    }
+
+    public AnnotationMirror getMarkerAnnotation() {
+        return markerAnnotation;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + " [method = " + method + "]";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.template;
+
+import static com.oracle.truffle.codegen.processor.Utils.*;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
+
+public abstract class TemplateMethodParser<E extends TemplateMethod> {
+
+    private final ProcessorContext context;
+
+    public TemplateMethodParser(ProcessorContext context) {
+        this.context = context;
+    }
+
+    public ProcessorContext getContext() {
+        return context;
+    }
+
+    public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror);
+
+    public abstract E create(TemplateMethod method);
+
+    public abstract Class<? extends Annotation> getAnnotationType();
+
+    public final E parse(ExecutableElement method, AnnotationMirror annotation, Template template) {
+        MethodSpec methodSpecification = createSpecification(method, annotation);
+        if (methodSpecification == null) {
+            return null;
+        }
+
+        ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
+        List<ParameterSpec> parameterSpecs = new ArrayList<>();
+        parameterSpecs.addAll(methodSpecification.getParameters());
+
+        ActualParameter returnTypeMirror = resolveTypeMirror(returnTypeSpec, method.getReturnType(), template);
+        if (returnTypeMirror == null) {
+            String expectedReturnType = createTypeSignature(returnTypeSpec, true);
+            String actualReturnType = Utils.getSimpleName(method.getReturnType());
+
+            String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
+                            createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
+
+            context.getLog().error(method, annotation, message);
+            return null;
+        }
+
+        Iterator< ? extends VariableElement> variableIterator = method.getParameters().iterator();
+        Iterator< ? extends ParameterSpec> specificationIterator = parameterSpecs.iterator();
+
+        List<ActualParameter> resolvedMirrors = new ArrayList<>();
+        VariableElement parameter = null;
+        ParameterSpec specification = null;
+        while (specificationIterator.hasNext() || specification != null) {
+            if (specification == null) {
+                specification = specificationIterator.next();
+            }
+
+            if (parameter == null && variableIterator.hasNext()) {
+                parameter = variableIterator.next();
+            }
+
+            if (parameter == null) {
+                if (specification.getCardinality() == Cardinality.MULTIPLE) {
+                    specification = null;
+                    continue;
+                } else if (!specification.isOptional()) {
+                    // non option type specification found -> argument missing
+                    String expectedType = createTypeSignature(specification, false);
+
+                    String message = String.format("Missing argument \"%s\".\nExpected signature: \n %s", expectedType,
+                                    createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
+
+                    context.getLog().error(method, message);
+                    return null;
+                } else {
+                    // specification is optional -> continue
+                    specification = null;
+                    continue;
+                }
+            }
+
+            ActualParameter resolvedMirror = resolveTypeMirror(specification, parameter.asType(), template);
+
+            if (resolvedMirror == null) {
+                if (specification.isOptional()) {
+                    specification = null;
+                    continue;
+                }
+
+                String expectedReturnType = createTypeSignature(specification, false);
+                String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName();
+
+                String message = String.format("The provided argument type \"%s\" does not match expected type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
+                                createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
+
+                context.getLog().error(parameter, message);
+                return null;
+            }
+
+            resolvedMirrors.add(resolvedMirror);
+            parameter = null; // consume parameter
+
+            if (specification.getCardinality() != Cardinality.MULTIPLE) {
+                specification = null;
+            }
+        }
+
+        if (variableIterator.hasNext()) {
+            parameter = variableIterator.next();
+            String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName();
+            String message = String.format("No argument expected but found \"%s\".\nExpected signature: \n %s", actualReturnType,
+                            createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs));
+
+            context.getLog().error(parameter, message);
+            return null;
+        }
+
+        ActualParameter[] paramMirrors = resolvedMirrors.toArray(new ActualParameter[resolvedMirrors.size()]);
+        return create(new TemplateMethod(methodSpecification, method, annotation, returnTypeMirror, paramMirrors));
+    }
+
+    private ActualParameter resolveTypeMirror(ParameterSpec specification, TypeMirror mirror, Template typeSystem) {
+        TypeMirror resolvedType = mirror;
+        if (hasError(resolvedType)) {
+            resolvedType = context.resolveNotYetCompiledType(mirror, typeSystem);
+        }
+
+        if (!specification.matches(resolvedType)) {
+            return null;
+        }
+        return new ActualParameter(specification, resolvedType);
+    }
+
+    public static String createExpectedSignature(String methodName, ParameterSpec returnType, List< ? extends ParameterSpec> parameters) {
+        StringBuilder b = new StringBuilder();
+
+        b.append("    ");
+        b.append(createTypeSignature(returnType, true));
+
+        b.append(" ");
+        b.append(methodName);
+        b.append("(");
+
+        for (int i = 0; i < parameters.size(); i++) {
+            ParameterSpec specification = parameters.get(i);
+            if (specification.isOptional()) {
+                b.append("[");
+            }
+            if (specification.getCardinality() == Cardinality.MULTIPLE) {
+                b.append("{");
+            }
+
+            b.append(createTypeSignature(specification, false));
+
+            if (specification.isOptional()) {
+                b.append("]");
+            }
+
+            if (specification.getCardinality() == Cardinality.MULTIPLE) {
+                b.append("}");
+            }
+
+            if (i < parameters.size() - 1) {
+                b.append(", ");
+            }
+
+        }
+
+        b.append(")");
+
+        TypeMirror[] types = null;
+
+        //TODO allowed types may differ so different <Any> must be generated.
+        if (returnType.getAllowedTypes().length > 1) {
+            types = returnType.getAllowedTypes();
+        }
+        for (ParameterSpec param : parameters) {
+            if (param.getAllowedTypes().length > 1) {
+                types = param.getAllowedTypes();
+            }
+        }
+        if (types != null) {
+            b.append("\n\n    ");
+            b.append("<Any> = {");
+            String separator = "";
+            for (TypeMirror type : types) {
+                b.append(separator).append(Utils.getSimpleName(type));
+                separator = ", ";
+            }
+            b.append("}");
+        }
+        return b.toString();
+    }
+
+    private static String createTypeSignature(ParameterSpec spec, boolean typeOnly) {
+        StringBuilder builder = new StringBuilder();
+        if (spec.getAllowedTypes().length > 1) {
+            builder.append("<Any>");
+        } else if (spec.getAllowedTypes().length == 1) {
+            builder.append(Utils.getSimpleName(spec.getAllowedTypes()[0]));
+        } else {
+            builder.append("void");
+        }
+        if (!typeOnly) {
+            builder.append(" ");
+            builder.append(spec.getName());
+        }
+        return builder.toString();
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.template;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.api.element.*;
+import com.oracle.truffle.codegen.processor.ext.*;
+
+public abstract class TemplateParser<M extends Template> extends AbstractParser<M> {
+
+    private final ExtensionParser extensionParser;
+
+    public TemplateParser(ProcessorContext c) {
+        super(c);
+        extensionParser = new ExtensionParser(c);
+    }
+
+    public ExtensionParser getExtensionParser() {
+        return extensionParser;
+    }
+
+    protected boolean verifyExclusiveMethodAnnotation(TypeElement type, Class<?> ... annotationTypes) {
+        boolean valid = true;
+        List<ExecutableElement> methods = ElementFilter.methodsIn(type.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()));
+                }
+
+                for (AnnotationMirror mirror : foundAnnotations) {
+                    context.getLog().error(method, mirror, "Non exclusive usage of annotations %s.", annotationNames);
+                }
+                valid = false;
+            }
+        }
+        return valid;
+    }
+
+    protected boolean verifyTemplateType(TypeElement template, AnnotationMirror annotation) {
+        // annotation type on class path!?
+        boolean valid = true;
+        TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName());
+        if (annotationTypeElement == null) {
+            log.error(template, annotation, "Required class " + getAnnotationType().getName() + " is not on the classpath.");
+            valid = false;
+        }
+        if (template.getModifiers().contains(Modifier.PRIVATE)) {
+            log.error(template, annotation, "The annotated class must have at least package protected visibility.");
+            valid = false;
+        }
+
+        if (template.getModifiers().contains(Modifier.FINAL)) {
+            log.error(template, annotation, "The annotated class must not be final.");
+            valid = false;
+        }
+
+        return valid;
+    }
+
+    protected <E extends TemplateMethod> List<E> parseMethods(Template template, TemplateMethodParser<E> parser) {
+        TypeElement type = template.getTemplateType();
+
+        List<ExecutableElement> methods = new ArrayList<>();
+        methods.addAll(ElementFilter.methodsIn(type.getEnclosedElements()));
+        if (template.getExtensionElements() != null) {
+            for (WritableElement e : template.getExtensionElements()) {
+                if (e instanceof ExecutableElement) {
+                    methods.add((ExecutableElement) e);
+                }
+            }
+        }
+
+        List<E> parsedMethods = new ArrayList<>();
+        boolean valid = true;
+        for (ExecutableElement method : methods) {
+            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, parser.getAnnotationType());
+            if (mirror != null) {
+                if (method.getModifiers().contains(Modifier.PRIVATE)) {
+                    log.error(method, "Methods annotated with @%s must not be private.",  parser.getAnnotationType().getSimpleName());
+                    valid = false;
+                    continue;
+                }
+                E parsedMethod = parser.parse(method, mirror, template);
+                if (parsedMethod != null) {
+                    parsedMethods.add(parsedMethod);
+                } else {
+                    valid = false;
+                }
+            }
+        }
+        if (!valid) {
+            return null;
+        }
+        return parsedMethods;
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.typesystem;
+
+import com.oracle.truffle.codegen.processor.template.*;
+
+
+public class GuardData extends TemplateMethod {
+
+    private final Template origin;
+
+    public GuardData(TemplateMethod method, Template origin) {
+        super(method);
+        this.origin = origin;
+    }
+
+    public Template getOrigin() {
+        return origin;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.typesystem;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
+
+
+public class GuardParser extends TypeSystemMethodParser<GuardData> {
+
+    private final Template origin;
+
+    public GuardParser(ProcessorContext context, TypeSystemData typeSystem, Template origin) {
+        super(context, typeSystem);
+        this.origin = origin;
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        List<ParameterSpec> specs = new ArrayList<>();
+        specs.add(new ParameterSpec("value1", getTypeSystem(), Kind.EXECUTE, false, Cardinality.ONE));
+        specs.add(new ParameterSpec("valueN", getTypeSystem(), Kind.EXECUTE, false, Cardinality.MULTIPLE));
+        ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class), Kind.ATTRIBUTE, false);
+        return new MethodSpec(returnTypeSpec, specs);
+    }
+
+    @Override
+    public GuardData create(TemplateMethod method) {
+        return new GuardData(method, origin);
+    }
+
+    @Override
+    public Class< ? extends Annotation> getAnnotationType() {
+        return GuardCheck.class;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastData.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.codegen.processor.typesystem;
+
+import com.oracle.truffle.codegen.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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java	Fri Dec 21 10:44:31 2012 -0800
@@ -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.codegen.processor.typesystem;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
+
+
+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, mirror, "as");
+        if (targetType == null) {
+            return null;
+        }
+        List<ParameterSpec> specs = new ArrayList<>();
+        specs.add(new ParameterSpec("value", getTypeSystem(), Kind.EXECUTE, false, Cardinality.ONE));
+        ParameterSpec returnTypeSpec = new ParameterSpec("returnType", targetType.getPrimitiveType(), Kind.ATTRIBUTE, false);
+        MethodSpec spec = new MethodSpec(returnTypeSpec, specs);
+        return spec;
+    }
+
+    @Override
+    public TypeCastData create(TemplateMethod method) {
+        TypeData targetType = findTypeByMethodName(method.getMethod(), method.getMarkerAnnotation(), "as");
+        ActualParameter parameter = method.findParameter("value");
+        return new TypeCastData(method, parameter.getActualTypeData(getTypeSystem()), targetType);
+    }
+
+    @Override
+    public Class< ? extends Annotation> getAnnotationType() {
+        return TypeCast.class;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckData.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.typesystem;
+
+import com.oracle.truffle.codegen.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;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.typesystem;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind;
+
+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, mirror, "is");
+        if (targetType == null) {
+            return null;
+        }
+        List<ParameterSpec> specs = new ArrayList<>();
+        specs.add(new ParameterSpec("value", getTypeSystem(), Kind.EXECUTE, false, Cardinality.ONE));
+        ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class), Kind.ATTRIBUTE, false);
+        MethodSpec spec = new MethodSpec(returnTypeSpec, specs);
+        return spec;
+    }
+
+    @Override
+    public TypeCheckData create(TemplateMethod method) {
+        TypeData checkedType = findTypeByMethodName(method.getMethod(), method.getMarkerAnnotation(), "is");
+        assert checkedType != null;
+        ActualParameter parameter = method.findParameter("value");
+        assert parameter != null;
+        return new TypeCheckData(method, checkedType, parameter.getActualTypeData(getTypeSystem()));
+    }
+
+    @Override
+    public Class< ? extends Annotation> getAnnotationType() {
+        return TypeCheck.class;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.typesystem;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+
+public class TypeData extends Template {
+
+    protected TypeSystemData typeSystem;
+    private final TypeMirror primitiveType;
+    private final TypeMirror boxedType;
+
+    private final List<TypeCastData> typeCasts = new ArrayList<>();
+    private final List<TypeCheckData> typeChecks = new ArrayList<>();
+
+    public TypeData(TypeElement templateType, AnnotationMirror annotation,
+                    TypeMirror primitiveType, TypeMirror boxedType) {
+        super(templateType, annotation);
+        this.primitiveType = primitiveType;
+        this.boxedType = boxedType;
+    }
+
+    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());
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.typesystem;
+
+import static com.oracle.truffle.codegen.processor.Utils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.ast.*;
+import com.oracle.truffle.codegen.processor.template.*;
+
+public class TypeSystemCodeGenerator extends CompilationUnitFactory<TypeSystemData> {
+
+    public TypeSystemCodeGenerator(ProcessorContext context) {
+        super(context);
+    }
+
+    public static String isTypeMethodName(TypeData type) {
+        return "is" + Utils.getSimpleName(type.getBoxedType());
+    }
+
+    public static String asTypeMethodName(TypeData type) {
+        return "as" + Utils.getSimpleName(type.getBoxedType());
+    }
+
+    public static String expectTypeMethodName(TypeData type) {
+        return "expect" + Utils.getSimpleName(type.getBoxedType());
+    }
+
+    /**
+     * 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(TypeClassFactory.typeName(typeSystem), typeSystem);
+        return Utils.findDeclaredField(type, TypeClassFactory.singletonName(typeSystem.getTemplateType().asType()));
+    }
+
+    @Override
+    protected void createChildren(TypeSystemData m) {
+        add(new TypeClassFactory(context), m);
+    }
+
+    protected static class TypeClassFactory extends ClassElementFactory<TypeSystemData> {
+
+        private static final String LOCAL_VALUE = "value";
+
+        public TypeClassFactory(ProcessorContext context) {
+            super(context);
+        }
+
+        @Override
+        public CodeTypeElement create(TypeSystemData typeSystem) {
+            String name = typeName(typeSystem);
+            CodeTypeElement clazz = createClass(typeSystem, modifiers(PUBLIC), name, typeSystem.getTemplateType().asType(), false);
+
+            clazz.getImplements().add(getContext().getTruffleTypes().getTypeConversion());
+
+            clazz.add(createConstructorUsingFields(modifiers(PROTECTED), clazz));
+            CodeVariableElement singleton = createSingleton(clazz);
+            clazz.add(singleton);
+
+            clazz.add(createGetTopType(typeSystem));
+            clazz.add(createConvertTo(typeSystem, singleton));
+
+            for (TypeData type : typeSystem.getTypes()) {
+                if (!type.isGeneric()) {
+                    CodeExecutableElement isType = createIsTypeMethod(type);
+                    if (isType != null) {
+                        clazz.add(isType);
+                    }
+                    CodeExecutableElement asType = createAsTypeMethod(type);
+                    if (asType != null) {
+                        clazz.add(asType);
+                    }
+
+                    for (TypeData sourceType : collectExpectSourceTypes(type)) {
+                        CodeExecutableElement expect = createExpectTypeMethod(type, sourceType);
+                        if (expect != null) {
+                            clazz.add(expect);
+                        }
+                    }
+                }
+            }
+
+            clazz.getEnclosedElements().addAll(typeSystem.getExtensionElements());
+
+            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 CodeExecutableElement createConvertTo(TypeSystemData typeSystem, CodeVariableElement singleton) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(Object.class), "convertTo");
+            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "targetType"));
+            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), "value"));
+
+            CodeTreeBuilder builder = method.createBuilder();
+
+            boolean first = true;
+            for (TypeData type : typeSystem.getTypes()) {
+                if (first) {
+                    builder.startIf();
+                    first = false;
+                } else {
+                    builder.startElseIf();
+                }
+                builder.string("targetType").string(" == ").typeLiteral(type.getBoxedType());
+                builder.end(); // if
+                builder.startBlock();
+
+                builder.startReturn();
+
+                if (typeEquals(type.getBoxedType(), getContext().getType(Object.class))) {
+                    builder.string("value");
+                } else {
+                    builder.string(singleton.getName()).string(".").startCall(asTypeMethodName(type)).string("value").end();
+                }
+
+                builder.end(); // return
+
+                builder.end(); // block
+            }
+
+            builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end();
+
+            return method;
+        }
+
+        private CodeExecutableElement createGetTopType(TypeSystemData typeSystem) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(Class.class), "getTopType");
+
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startReturn();
+            if (typeSystem.getTypes().length > 0) {
+                builder.typeLiteral(typeSystem.getTypes()[0].getBoxedType());
+            } else {
+                builder.null_();
+            }
+            builder.end(); // return
+
+            return method;
+        }
+
+        private static String typeName(TypeSystemData typeSystem) {
+            String name = getSimpleName(typeSystem.getTemplateType());
+            return name + "Gen";
+        }
+
+        private static String singletonName(TypeMirror type) {
+            return createConstantName(getSimpleName(type));
+        }
+
+        private CodeVariableElement createSingleton(CodeTypeElement clazz) {
+            CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(getModel().getTemplateType().asType()));
+            field.createInitBuilder().startNew(clazz.asType()).end();
+            return field;
+        }
+
+        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));
+
+            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();
+            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(null, TypeSystemCodeGenerator.isTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end().startBlock();
+            body.startReturn().startCall(null, 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.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.typesystem;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+
+public class TypeSystemData extends Template {
+
+    private final TypeData[] types;
+    private final TypeMirror[] primitiveTypeMirrors;
+    private final TypeMirror[] boxedTypeMirrors;
+
+    private final TypeMirror nodeType;
+    private final TypeMirror genericType;
+
+    private final TypeData voidType;
+
+    private List<GuardData> guards;
+
+
+    public TypeSystemData(TypeElement templateType, AnnotationMirror annotation,
+                    TypeData[] types, TypeMirror nodeType, TypeMirror genericType, TypeData voidType) {
+        super(templateType, annotation);
+        this.voidType = voidType;
+        this.types = types;
+        this.nodeType = nodeType;
+        this.genericType = genericType;
+
+        this.primitiveTypeMirrors = new TypeMirror[types.length];
+        for (int i = 0; i < types.length; i++) {
+            primitiveTypeMirrors[i] = types[i].getPrimitiveType();
+        }
+
+        this.boxedTypeMirrors = new TypeMirror[types.length];
+        for (int i = 0; i < types.length; i++) {
+            boxedTypeMirrors[i] = types[i].getBoxedType();
+        }
+
+        for (TypeData type : types) {
+            type.typeSystem = this;
+        }
+        if (voidType != null)  {
+            voidType.typeSystem = this;
+        }
+    }
+
+    public TypeData getVoidType() {
+        return voidType;
+    }
+
+    void setGuards(List<GuardData> guards) {
+        this.guards = guards;
+    }
+
+    public List<GuardData> getGuards() {
+        return guards;
+    }
+
+    public TypeData[] getTypes() {
+        return types;
+    }
+
+    public TypeMirror[] getPrimitiveTypeMirrors() {
+        return primitiveTypeMirrors;
+    }
+
+    public TypeMirror[] getBoxedTypeMirrors() {
+        return boxedTypeMirrors;
+    }
+
+    public TypeMirror getNodeType() {
+        return nodeType;
+    }
+
+    public TypeMirror getGenericType() {
+        return genericType;
+    }
+
+    public TypeData getGenericTypeData() {
+        TypeData result = types[types.length - 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 int findType(TypeMirror type) {
+        for (int i = 0; i < types.length; i++) {
+            if (Utils.typeEquals(types[i].getPrimitiveType(), type)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.typesystem;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.*;
+
+
+abstract class TypeSystemMethodParser<E extends TemplateMethod> extends TemplateMethodParser<E> {
+
+    private final TypeSystemData typeSystem;
+
+    public TypeSystemMethodParser(ProcessorContext context, TypeSystemData typeSystem) {
+        super(context);
+        this.typeSystem = typeSystem;
+    }
+
+    public TypeSystemData getTypeSystem() {
+        return typeSystem;
+    }
+
+    protected TypeData findTypeByMethodName(ExecutableElement method, AnnotationMirror annotationMirror, String prefix) {
+        String methodName = method.getSimpleName().toString();
+        if (!methodName.startsWith(prefix)) {
+            String annotationName = Utils.getSimpleName(annotationMirror.getAnnotationType());
+            getContext().getLog().error(method, "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 = typeSystem.findType(typeName);
+        if (type == null) {
+            String annotationName = TypeSystem.class.getSimpleName();
+            getContext().getLog().error(method, "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.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java	Fri Dec 21 10:44:31 2012 -0800
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.codegen.processor.typesystem;
+
+import static com.oracle.truffle.codegen.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.codegen.*;
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.operation.*;
+import com.oracle.truffle.codegen.processor.template.*;
+
+public class TypeSystemParser extends TemplateParser<TypeSystemData> {
+
+    public TypeSystemParser(ProcessorContext c) {
+        super(c);
+    }
+
+    @Override
+    public Class< ? extends Annotation> getAnnotationType() {
+        return TypeSystem.class;
+    }
+
+    @Override
+    protected TypeSystemData parse(Element element, AnnotationMirror mirror) {
+        TypeElement templateType = (TypeElement) element;
+        AnnotationMirror templateTypeAnnotation = mirror;
+
+        if (!verifyTemplateType(templateType, templateTypeAnnotation)) {
+            return null;
+        }
+
+        TypeData[] types = parseTypes(templateType, templateTypeAnnotation);
+        if (types == null) {
+            return null;
+        }
+
+        TypeMirror nodeType = Utils.getAnnotationValueType(templateTypeAnnotation, "nodeBaseClass");
+        TypeMirror genericType = context.getType(Object.class);
+
+        TypeData voidType = null;
+        if (Utils.getAnnotationValueBoolean(templateTypeAnnotation, "hasVoid")) {
+            voidType = new TypeData(templateType, templateTypeAnnotation, context.getType(void.class), context.getType(Void.class));
+        }
+
+        TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation, types, nodeType, genericType, voidType);
+
+        if (!verifyNodeBaseType(typeSystem)) {
+            return null;
+        }
+
+        if (!verifyExclusiveMethodAnnotation(templateType, TypeCast.class, TypeCheck.class, GuardCheck.class)) {
+            return null;
+        }
+
+        typeSystem.setExtensionElements(getExtensionParser().parseAll(templateType));
+
+        List<TypeCastData> casts = parseMethods(typeSystem, new TypeCastParser(context, typeSystem));
+        List<TypeCheckData> checks = parseMethods(typeSystem, new TypeCheckParser(context, typeSystem));
+        List<GuardData> guards = parseMethods(typeSystem, new GuardParser(context, typeSystem, typeSystem));
+
+        if (casts == null || checks == null || guards == null) {
+            return null;
+        }
+
+        for (TypeCheckData check : checks) {
+            check.getCheckedType().addTypeCheck(check);
+        }
+
+        for (TypeCastData cast : casts) {
+            cast.getTargetType().addTypeCast(cast);
+        }
+
+        typeSystem.setGuards(guards);
+
+        if (!verifyGenericTypeChecksAndCasts(types)) {
+            return null;
+        }
+
+        if (!verifyMethodSignatures(element, types)) {
+            return null;
+        }
+
+        if (!verifyNamesUnique(templateType, templateTypeAnnotation, types)) {
+            return null;
+        }
+
+        return typeSystem;
+    }
+
+    private boolean verifyGenericTypeChecksAndCasts(TypeData[] types) {
+        boolean valid = true;
+        for (TypeData type : types) {
+            if (!type.getTypeChecks().isEmpty()) {
+                boolean hasGeneric = false;
+                for (TypeCheckData typeCheck : type.getTypeChecks()) {
+                    if (typeCheck.isGeneric()) {
+                        hasGeneric = true;
+                        break;
+                    }
+                }
+                if (!hasGeneric) {
+                    log.error(type.getTypeSystem().getTemplateType(),
+                                    "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());
+                    valid = false;
+                }
+            }
+            if (!type.getTypeCasts().isEmpty()) {
+                boolean hasGeneric = false;
+                for (TypeCastData typeCast : type.getTypeCasts()) {
+                    if (typeCast.isGeneric()) {
+                        hasGeneric = true;
+                        break;
+                    }
+                }
+                if (!hasGeneric) {
+                    log.error(type.getTypeSystem().getTemplateType(),
+                                    "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());
+                    valid = false;
+                }
+            }
+        }
+        return valid;
+    }
+
+    private boolean verifyNodeBaseType(TypeSystemData typeSystem) {
+        List<TypeData> types = new ArrayList<>(Arrays.asList(typeSystem.getTypes()));
+        if (typeSystem.getVoidType() != null) {
+            types.add(typeSystem.getVoidType());
+        }
+
+        TypeMirror[] args = new TypeMirror[]{context.getTruffleTypes().getFrame()};
+        List<String> missingMethods = new ArrayList<>();
+        for (TypeData typeData : types) {
+            String methodName = OperationCodeGenerator.executeMethodName(typeData);
+            ExecutableElement declared = Utils.getDeclaredMethodRecursive(Utils.fromTypeMirror(typeSystem.getNodeType()), methodName, args);
+            if (declared == null || declared.getModifiers().contains(Modifier.FINAL)) {
+                missingMethods.add(String.format("public %s %s(%s)",
+                                Utils.getSimpleName(typeData.getPrimitiveType()), methodName,
+                                Utils.getSimpleName(context.getTruffleTypes().getFrame())));
+            }
+        }
+
+        if (!missingMethods.isEmpty()) {
+            log.error(typeSystem.getTemplateType(), typeSystem.getTemplateTypeAnnotation(),
+                            Utils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "nodeBaseClass"),
+                            "The class '%s' does not declare the required non final method(s) %s.",
+                            Utils.getQualifiedName(typeSystem.getNodeType()), missingMethods);
+            return false;
+        }
+
+        return true;
+    }
+
+    private TypeData[] parseTypes(TypeElement templateType, AnnotationMirror templateTypeAnnotation) {
+        List<TypeMirror> typeMirrors = Utils.getAnnotationValueList(templateTypeAnnotation, "types");
+        if (typeMirrors.size() == 0) {
+            log.error(templateType, templateTypeAnnotation, "At least one type child must be defined.");
+            return null;
+        }
+
+        final AnnotationValue annotationValue = Utils.getAnnotationValue(templateTypeAnnotation, "types");
+        final TypeMirror objectType = context.getType(Object.class);
+
+        List<TypeData> types = new ArrayList<>();
+        for (TypeMirror primitiveType : typeMirrors) {
+
+            if (isPrimitiveWrapper(primitiveType)) {
+                log.error(templateType, templateTypeAnnotation, annotationValue,
+                                "Types must not contain primitive wrapper types.");
+                continue;
+            }
+
+            TypeMirror boxedType = primitiveType;
+            if (boxedType.getKind().isPrimitive()) {
+                boxedType = processingEnv.getTypeUtils().boxedClass((PrimitiveType) boxedType).asType();
+            }
+
+            if (Utils.typeEquals(boxedType, objectType)) {
+                log.error(templateType, templateTypeAnnotation, annotationValue,
+                                "Types must not contain the generic type java.lang.Object.");
+                continue;
+            }
+
+            types.add(new TypeData(templateType, templateTypeAnnotation, primitiveType, boxedType));
+        }
+
+        verifyTypeOrder(templateType, templateTypeAnnotation, annotationValue, types);
+
+        types.add(new TypeData(templateType, templateTypeAnnotation, objectType, objectType));
+
+        return types.toArray(new TypeData[types.size()]);
+    }
+
+    private void verifyTypeOrder(TypeElement templateType, AnnotationMirror templateTypeAnnotation, AnnotationValue annotationValue, 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))) {
+                log.error(templateType, templateTypeAnnotation, annotationValue,
+                                "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 boolean verifyMethodSignatures(Element element, TypeData[] types) {
+        Set<String> generatedIsMethodNames = new HashSet<>();
+        Set<String> generatedAsMethodNames = new HashSet<>();
+        Set<String> generatedExpectMethodNames = new HashSet<>();
+
+        for (TypeData typeData : types) {
+            generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData));
+            generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData));
+            generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData));
+        }
+
+        boolean valid = true;
+        List<ExecutableElement> methods = ElementFilter.methodsIn(element.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)) {
+                valid &= verifyIsMethod(method);
+            } else if (generatedAsMethodNames.contains(methodName)) {
+                valid &= verifyAsMethod(method);
+            } else if (generatedExpectMethodNames.contains(methodName)) {
+                valid &= verifyExpectMethod(method);
+            }
+        }
+        return valid;
+    }
+
+    private boolean verifyIsMethod(ExecutableElement method) {
+        AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCheck.class);
+        if (mirror == null) {
+            log.error(method, "Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName());
+            return false;
+        }
+        return true;
+    }
+
+    private boolean verifyAsMethod(ExecutableElement method) {
+        AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCast.class);
+        if (mirror == null) {
+            log.error(method, "Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName());
+            return false;
+        }
+        return true;
+    }
+
+    private boolean verifyExpectMethod(ExecutableElement method) {
+        log.error(method, "Method starting with the pattern expect${typeName} must not be declared manually.");
+        return false;
+    }
+
+    private boolean verifyNamesUnique(TypeElement templateType, AnnotationMirror templateTypeAnnotation, TypeData[] types) {
+        boolean valid = true;
+        for (int i = 0; i < types.length; i++) {
+            for (int j = i + 1; j < types.length; j++) {
+                String name1 = Utils.getSimpleName(types[i].getBoxedType());
+                String name2 = Utils.getSimpleName(types[j].getBoxedType());
+                if (name1.equalsIgnoreCase(name2)) {
+                    log.error(templateType, templateTypeAnnotation, "Two types result in the same name: %s, %s.", name1, name2);
+                    valid = false;
+                }
+            }
+        }
+        return valid;
+    }
+}
--- a/mx/commands.py	Fri Dec 21 10:21:24 2012 +0100
+++ b/mx/commands.py	Fri Dec 21 10:44:31 2012 -0800
@@ -396,7 +396,14 @@
         log = open(logFile, 'w')
     ret = False
     while True:
-        line = stdout.readline().decode(sys.stdout.encoding)
+        
+        # encoding may be None on windows plattforms
+        if sys.stdout.encoding is None:
+            encoding = 'utf-8'
+        else:
+            encoding = sys.stdout.encoding
+        
+        line = stdout.readline().decode(encoding)
         if logFile:
             log.write(line.encode('utf-8'))
         line = line.strip()
--- a/mx/projects	Fri Dec 21 10:21:24 2012 +0100
+++ b/mx/projects	Fri Dec 21 10:44:31 2012 -0800
@@ -10,6 +10,9 @@
 library@CHECKSTYLE@path=lib/checkstyle-5.5-all.jar
 library@CHECKSTYLE@urls=jar:http://sourceforge.net/projects/checkstyle/files/checkstyle/5.5/checkstyle-5.5-bin.zip/download!/checkstyle-5.5/checkstyle-5.5-all.jar
 
+library@ANT_JAR_TOOL@path=lib/ant-jar-tool.jar
+library@ANT_JAR_TOOL@urls=http://lafo.ssw.uni-linz.ac.at/ant-jar-tool/ant-jar-tool.jar
+
 library@DACAPO@path=lib/dacapo-9.12-bach.jar
 library@DACAPO@urls=http://softlayer.dl.sourceforge.net/project/dacapobench/9.12-bach/dacapo-9.12-bach.jar
 
@@ -269,3 +272,17 @@
 project@com.oracle.truffle.api.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.truffle.api.test@javaCompliance=1.7
 
+# truffle.api.codegen
+project@com.oracle.truffle.api.codegen@subDir=graal
+project@com.oracle.truffle.api.codegen@sourceDirs=src
+project@com.oracle.truffle.api.codegen@dependencies=com.oracle.truffle.api
+project@com.oracle.truffle.api.codegen@checkstyle=com.oracle.graal.graph
+project@com.oracle.truffle.api.codegen@javaCompliance=1.7
+
+# truffle.codegen.processor
+project@com.oracle.truffle.codegen.processor@subDir=graal
+project@com.oracle.truffle.codegen.processor@sourceDirs=src
+project@com.oracle.truffle.codegen.processor@dependencies=com.oracle.truffle.api.codegen
+project@com.oracle.truffle.codegen.processor@checkstyle=com.oracle.graal.graph
+project@com.oracle.truffle.codegen.processor@javaCompliance=1.7
+
--- a/mxtool/mx.py	Fri Dec 21 10:21:24 2012 +0100
+++ b/mxtool/mx.py	Fri Dec 21 10:44:31 2012 -0800
@@ -188,14 +188,17 @@
             if not exists(s):
                 os.mkdir(s)
 
-    def all_deps(self, deps, includeLibs, includeSelf=True):
+    def all_deps(self, deps, includeLibs, includeSelf=True, includeAnnotationProcessors=False):
         """
         Add the transitive set of dependencies for this project, including
         libraries if 'includeLibs' is true, to the 'deps' list.
         """
+        childDeps = list(self.deps)
+        if includeAnnotationProcessors and hasattr(self, 'annotationProcessors') and len(self.annotationProcessors) > 0:
+            childDeps = self.annotationProcessors + childDeps
         if self in deps:
             return deps
-        for name in self.deps:
+        for name in childDeps:
             assert name != self.name
             dep = _libs.get(name, None)
             if dep is not None:
@@ -208,7 +211,7 @@
                         abort('project named ' + name + ' required by ' + self.name + ' is ignored')
                     abort('dependency named ' + name + ' required by ' + self.name + ' is not found')
                 if not dep in deps:
-                    dep.all_deps(deps, includeLibs)
+                    dep.all_deps(deps, includeLibs=includeLibs, includeAnnotationProcessors=includeAnnotationProcessors)
         if not self in deps and includeSelf:
             deps.append(self)
         return deps
@@ -464,7 +467,7 @@
             srcDirs = pop_list(attrs, 'sourceDirs')
             deps = pop_list(attrs, 'dependencies')
             ap = pop_list(attrs, 'annotationProcessors')
-            deps += ap
+            #deps += ap
             javaCompliance = attrs.pop('javaCompliance', None)
             subDir = attrs.pop('subDir', None);
             if subDir is None:
@@ -478,9 +481,6 @@
                 abort('javaCompliance property required for non-native project ' + name)
             if len(ap) > 0:
                 p.annotationProcessors = ap
-            apc = pop_list(attrs, 'annotationProcessorClasses')
-            if len(apc) > 0:
-                p.annotationProcessorClasses = apc
             p.__dict__.update(attrs)
             self.projects.append(p)
 
@@ -729,7 +729,7 @@
                     entryPath = zi.filename
                     yield zf, entryPath
 
-def sorted_deps(projectNames=None, includeLibs=False):
+def sorted_deps(projectNames=None, includeLibs=False, includeAnnotationProcessors=False):
     """
     Gets projects and libraries sorted such that dependencies
     are before the projects that depend on them. Unless 'includeLibs' is
@@ -742,7 +742,7 @@
         projects = [project(name) for name in projectNames]
 
     for p in projects:
-        p.all_deps(deps, includeLibs)
+        p.all_deps(deps, includeLibs=includeLibs, includeAnnotationProcessors=includeAnnotationProcessors)
     return deps
 
 class ArgParser(ArgumentParser):
@@ -1296,7 +1296,7 @@
     if args.only is not None:
         sortedProjects = [project(name) for name in args.only.split(',')]
     else:
-        sortedProjects = sorted_deps(projects)
+        sortedProjects = sorted_deps(projects, includeAnnotationProcessors=True)
     
     for p in sortedProjects:
         if p.native:
@@ -1380,6 +1380,8 @@
                             log('could not file .class directive in Jasmin source: ' + src)
                     else:
                         dst = join(outputDir, src[len(sourceDir) + 1:])
+                        if not exists(dirname(dst)):
+                            os.makedirs(dirname(dst))
                         if exists(dirname(dst)) and (not exists(dst) or os.path.getmtime(dst) != os.path.getmtime(src)):
                             shutil.copyfile(src, dst)
 
@@ -1410,18 +1412,12 @@
             javacArgs += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(java().debug_port)]
 
         if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
-            annotationProcessors = []
-            for apProject in p.annotationProcessors:
-                apClasses = project(apProject).annotationProcessorClasses
-                if len(apClasses) == 0:
-                    abort("Project " + p + " specifies " + apProject + " as an annotation processor but " + apProject + " does not specifiy any annotation processor class")
-                annotationProcessors += apClasses
-            
+            processorPath = classpath(p.annotationProcessors, resolve=True)
             genDir = p.source_gen_dir();
             if exists(genDir):
                 shutil.rmtree(genDir)
             os.mkdir(genDir)
-            javacArgs += ['-processor', ",".join(annotationProcessors), "-s", genDir]
+            javacArgs += ['-processorpath', join(processorPath), '-s', genDir] 
         else:
             javacArgs += ['-proc:none']
 
@@ -1467,37 +1463,53 @@
         return args
     return None
 
-def processorjars(args):
-    hasProcessorJars = []
+def processorjars():
+    projects = set([])
     
     for p in sorted_deps():
-        if hasattr(p, 'annotationProcessorClasses') and len(p.annotationProcessorClasses) > 0:
-            hasProcessorJars.append(p)
+        if _needsEclipseJarBuild(p):
+            projects.add(p)
             
-    if len(hasProcessorJars) <= 0:
+    if len(projects) <= 0:
         return
     
-    build(['--projects', ",".join(map(lambda p: p.name, hasProcessorJars))])
-
-    for p in hasProcessorJars:
-        spDir = join(p.output_dir(), 'META-INF', 'services')
-        if not exists(spDir):
-            os.makedirs(spDir)
-        spFile = join(spDir, 'javax.annotation.processing.Processor')
-        with open(spFile, 'w') as fp:
-            fp.writelines(p.annotationProcessorClasses)
-        created = False
-        for dep in p.all_deps([], False):
-            if created:
-                cmd = 'uf'
-            else:
-                cmd = 'cf'
-                created = True
-            jarCmd = [java().jar, cmd, join(p.dir, p.name + 'AnnotationProcessor.jar'), '-C', dep.output_dir(), '.']
-            subprocess.check_call(jarCmd)
-            log('added ' + dep.name + ' to ' + p.name + '.jar');
+    build(['--projects', ",".join(map(lambda p: p.name, projects))])
+
+    for p in projects:
+        targetJar = join(p.dir, p.name + '.jar')
+        jar(targetJar, [p.output_dir()])
             
 
+def jar(destFileName, dirs):
+    lib = library("ANT_JAR_TOOL", fatalIfMissing=False)
+    
+    if lib is None :
+        log('No library ANT_JAR_TOOL defined. Falling back to JDK Jar tool.');
+        _java_jar_tool(destFileName, dirs)
+    else:
+        _ant_jar_tool(lib, destFileName, dirs)
+
+def _java_jar_tool(destFileName, dirs):
+    created = False
+    for directory in dirs:
+        if created:
+            cmd = 'uf'
+        else:
+            cmd = 'cf'
+            created = True
+        jarCmd = [java().jar, cmd, destFileName, '-C', directory, '.']
+        subprocess.check_call(jarCmd)
+    
+def _ant_jar_tool(lib, destFileName, dirs):
+    antJar = lib.get_path(True)
+    
+    jarCmd = [java().java, '-jar', antJar, destFileName]
+    for directory in dirs :
+        jarCmd.append(directory)
+        
+    subprocess.check_call(jarCmd)
+
+
 def canonicalizeprojects(args):
     """process all project files to canonicalize the dependencies
 
@@ -1866,7 +1878,7 @@
     if suite is None:
         suite = _mainSuite
         
-    processorjars([])
+    processorjars()
 
     for p in projects():
         if p.native:
@@ -1884,6 +1896,13 @@
                 os.mkdir(srcDir)
             out.element('classpathentry', {'kind' : 'src', 'path' : src})
 
+        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
+            genDir = p.source_gen_dir();
+            if exists(genDir):
+                shutil.rmtree(genDir)
+            os.mkdir(genDir)
+            out.element('classpathentry', {'kind' : 'src', 'path' : 'src_gen'})
+
         # Every Java program depends on the JRE
         out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.jdt.launching.JRE_CONTAINER'})
 
@@ -1975,6 +1994,23 @@
                 out.element('name', data=buildCommand)
                 out.element('arguments', data='')
                 out.close('buildCommand')
+
+        if (_needsEclipseJarBuild(p)):
+            out.open('buildCommand')
+            out.element('name', data='org.eclipse.ui.externaltools.ExternalToolBuilder')
+            out.element('triggers', data='auto,full,incremental,')
+            out.open('arguments')
+            out.open('dictionary')
+            out.element('key', data = 'LaunchConfigHandle')
+            out.element('value', data = _genEclipseJarBuild(p))
+            out.close('dictionary')
+            out.open('dictionary')
+            out.element('key', data = 'incclean')
+            out.element('value', data = 'true')
+            out.close('dictionary')
+            out.close('arguments')
+            out.close('buildCommand')       
+                
         out.close('buildSpec')
         out.open('natures')
         out.element('nature', data='org.eclipse.jdt.core.javanature')
@@ -2010,7 +2046,7 @@
             out.element('factorypathentry', {'kind' : 'PLUGIN', 'id' : 'org.eclipse.jst.ws.annotations.core', 'enabled' : 'true', 'runInBatchMode' : 'false'})
             for ap in p.annotationProcessors:
                 apProject = project(ap)
-                out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + apProject.name + '/' + apProject.name + 'AnnotationProcessor.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'})
+                out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + apProject.name + '/' + apProject.name + '.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'})
                 for dep in apProject.all_deps([], True):
                     if dep.isLibrary():
                         if not hasattr(dep, 'eclipse.container') and not hasattr(dep, 'eclipse.project'):
@@ -2022,11 +2058,79 @@
                                     # safest to simply use absolute paths.
                                     path = join(suite.dir, path)
                                 out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : path, 'enabled' : 'true', 'runInBatchMode' : 'false'})
+                    else:
+                        out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + dep.name + '/' + dep.name + '.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'})
             out.close('factorypath')
             update_file(join(p.dir, '.factorypath'), out.xml(indent='\t', newl='\n'))
 
     make_eclipse_attach('localhost', '8000', deps=projects())
 
+
+def _needsEclipseJarBuild(p):
+    processors = set([])
+    
+    for otherProject in projects():
+        if hasattr(otherProject, 'annotationProcessors') and len(otherProject.annotationProcessors) > 0:
+            for processorName in otherProject.annotationProcessors:
+                processors.add(project(processorName, fatalIfMissing=True))
+                 
+    if p in processors:
+        return True
+    
+    for otherProject in processors:
+        deps = otherProject.all_deps([], True)
+        if p in deps:
+            return True
+    
+    return False
+
+def _genEclipseJarBuild(p):
+    externalToolDir = '.externalToolBuilders'
+    relPath = join(externalToolDir, 'Jar.launch') 
+    absPath = join(p.dir, relPath)
+    
+    if not exists(join(p.dir, externalToolDir)):
+        os.makedirs(join(p.dir, externalToolDir))
+    
+    antOut = XMLDoc()
+    antOut.open('project', {'name' : p.name, 'default' : 'default', 'basedir' : '.'})
+    antOut.open('target', {'name' : 'default'})
+    antOut.open('jar', {'destfile' : p.name + '.jar'})
+    antOut.element('fileset', {'dir' : p.output_dir()})
+    antOut.close('jar')
+    antOut.close('target')
+    antOut.close('project')
+    
+    update_file(join(p.dir, 'eclipse-build.xml'), antOut.xml(indent='\t', newl='\n'))
+    
+    launchOut = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
+<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/>
+<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
+<booleanAttribute key="org.eclipse.ant.uiSET_INPUTHANDLER" value="false"/>
+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;resources&gt;&#13;&#10;&lt;item path=&quot;/""" + p.name + """&quot; type=&quot;4&quot;/&gt;&#13;&#10;&lt;/resources&gt;}"/>
+<booleanAttribute key="org.eclipse.debug.core.capture_output" value="false"/>
+<booleanAttribute key="org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON" value="false"/>
+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
+<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.ant.internal.launching.remote.InternalAntRunner"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value=""" + '"' + p.name + '"' + """/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/""" + p.name + """/eclipse-build.xml}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="auto,full,incremental"/>
+<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/""" + p.name + """}"/>
+<stringAttribute key="process_factory_id" value="org.eclipse.ant.ui.remoteAntProcessFactory"/>
+</launchConfiguration>
+"""
+    update_file(absPath, launchOut)
+    
+    return "<project>/.externalToolBuilders/Jar.launch"
+
+
+
+
 def netbeansinit(args, suite=None):
     """(re)generate NetBeans project configurations"""
 
@@ -2063,9 +2167,10 @@
         out.element('explicit-platform', {'explicit-source-supported' : 'true'})
         out.open('source-roots')
         out.element('root', {'id' : 'src.dir'})
+        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
+            out.element('root', {'id' : 'src.ap-source-output.dir'})
         out.close('source-roots')
         out.open('test-roots')
-        out.element('root', {'id' : 'test.src.dir'})
         out.close('test-roots')
         out.close('data')
 
@@ -2099,12 +2204,18 @@
         out = StringIO.StringIO()
         jdkPlatform = 'JDK_' + java().version
 
+        annotationProcessorEnabled = "false"
+        annotationProcessorReferences = ""
+        annotationProcessorSrcFolder = ""
+        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
+            annotationProcessorEnabled = "true"
+            annotationProcessorSrcFolder = "src.ap-source-output.dir=${build.generated.sources.dir}/ap-source-output"
+
         content = """
-annotation.processing.enabled=false
-annotation.processing.enabled.in.editor=false
+annotation.processing.enabled=""" + annotationProcessorEnabled + """
+annotation.processing.enabled.in.editor=""" + annotationProcessorEnabled + """
 annotation.processing.processors.list=
 annotation.processing.run.all.processors=true
-annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
 application.title=""" + p.name + """
 application.vendor=mx
 build.classes.dir=${build.dir}
@@ -2134,15 +2245,11 @@
 # Space-separated list of extra javac options
 javac.compilerargs=
 javac.deprecation=false
-javac.processorpath=\\
-    ${javac.classpath}
 javac.source=1.7
 javac.target=1.7
 javac.test.classpath=\\
     ${javac.classpath}:\\
     ${build.classes.dir}
-javac.test.processorpath=\\
-    ${javac.test.classpath}
 javadoc.additionalparam=
 javadoc.author=false
 javadoc.encoding=${source.encoding}
@@ -2170,7 +2277,8 @@
 run.test.classpath=\\
     ${javac.test.classpath}:\\
     ${build.test.classes.dir}
-test.src.dir=
+test.src.dir=./test
+""" + annotationProcessorSrcFolder + """
 source.encoding=UTF-8""".replace(':', os.pathsep).replace('/', os.sep)
         print >> out, content
 
@@ -2188,7 +2296,19 @@
                 print >> out, 'src.' + src + '.dir=${' + ref + '}'
 
         javacClasspath = []
-        for dep in p.all_deps([], True):
+        
+        deps = p.all_deps([], True)
+        annotationProcessorOnlyDeps = []
+        if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0:
+            for ap in p.annotationProcessors:
+                apProject = project(ap)
+                if not apProject in deps:
+                    deps.append(apProject)
+                    annotationProcessorOnlyDeps.append(apProject)
+        
+        annotationProcessorReferences = [];
+        
+        for dep in deps:
             if dep == p:
                 continue;
 
@@ -2208,11 +2328,16 @@
                 print >> out, 'project.' + n + '=' + relDepPath
                 print >> out, ref + '=${project.' + n + '}/dist/' + dep.name + '.jar'
 
-            javacClasspath.append('${' + ref + '}')
+            if not dep in annotationProcessorOnlyDeps:
+                javacClasspath.append('${' + ref + '}')
+            else:
+                annotationProcessorReferences.append('${' + ref + '}')
+                annotationProcessorReferences +=  ":\\\n    ${" + ref + "}"
 
         print >> out, 'javac.classpath=\\\n    ' + (os.pathsep + '\\\n    ').join(javacClasspath)
-
-
+        print >> out, 'javac.test.processorpath=${javac.test.classpath}\\\n    ' + (os.pathsep + '\\\n    ').join(annotationProcessorReferences)
+        print >> out, 'javac.processorpath=${javac.classpath}\\\n    ' + (os.pathsep + '\\\n    ').join(annotationProcessorReferences)
+    
         updated = update_file(join(p.dir, 'nbproject', 'project.properties'), out.getvalue()) or updated
         out.close()
 
@@ -2223,7 +2348,6 @@
 
 def ideclean(args, suite=None):
     """remove all Eclipse and NetBeans project configurations"""
-
     def rm(path):
         if exists(path):
             os.remove(path)
@@ -2233,10 +2357,17 @@
             continue
 
         shutil.rmtree(join(p.dir, '.settings'), ignore_errors=True)
+        shutil.rmtree(join(p.dir, '.externalToolBuilders'), ignore_errors=True)
         shutil.rmtree(join(p.dir, 'nbproject'), ignore_errors=True)
         rm(join(p.dir, '.classpath'))
         rm(join(p.dir, '.project'))
         rm(join(p.dir, 'build.xml'))
+        rm(join(p.dir, 'eclipse-build.xml'))
+        try:
+            rm(join(p.dir, p.name + '.jar'))
+        except:
+            log("Error removing {0}".format(p.name + '.jar'))
+            
 
 def ideinit(args, suite=None):
     """(re)generate Eclipse and NetBeans project configurations"""