changeset 8237:6b74ffe38183

Implemented support for executing nodes in @Children fields.
author Christian Humer <christian.humer@gmail.com>
date Fri, 01 Mar 2013 17:03:57 +0100
parents dbbdc0a30a16
children 0b48dc5f37c3
files 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/node/MethodParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.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/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/typesystem/TypeCastParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java
diffstat 14 files changed, 229 insertions(+), 165 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Mon Feb 25 20:54:33 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java	Fri Mar 01 17:03:57 2013 +0100
@@ -591,6 +591,14 @@
         }
         String qualified1 = getQualifiedName(type1);
         String qualified2 = getQualifiedName(type2);
+
+        if (type1.getKind() == TypeKind.ARRAY || type2.getKind() == TypeKind.ARRAY) {
+            if (type1.getKind() == TypeKind.ARRAY && type2.getKind() == TypeKind.ARRAY) {
+                return typeEquals(((ArrayType) type1).getComponentType(), ((ArrayType) type2).getComponentType());
+            } else {
+                return false;
+            }
+        }
         return qualified1.equals(qualified2);
     }
 
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java	Mon Feb 25 20:54:33 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java	Fri Mar 01 17:03:57 2013 +0100
@@ -27,7 +27,7 @@
 import javax.lang.model.element.*;
 
 import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind;
+import com.oracle.truffle.codegen.processor.node.NodeFieldData.*;
 import com.oracle.truffle.codegen.processor.template.*;
 import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
 
@@ -56,8 +56,11 @@
 
     protected final MethodSpec createDefaultMethodSpec(String shortCircuitName) {
         List<ParameterSpec> defaultParameters = new ArrayList<>();
-        ParameterSpec frameSpec = new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), true);
-        defaultParameters.add(frameSpec);
+
+        if (getNode().supportsFrame()) {
+            ParameterSpec frameSpec = new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), true);
+            defaultParameters.add(frameSpec);
+        }
 
         for (NodeFieldData field : getNode().getFields()) {
             if (field.getExecutionKind() == ExecutionKind.IGNORE) {
@@ -65,7 +68,12 @@
             }
 
             if (field.getExecutionKind() == ExecutionKind.DEFAULT) {
-                defaultParameters.add(createValueParameterSpec(field.getName(), field.getNodeData(), false));
+                ParameterSpec spec = createValueParameterSpec(field.getName(), field.getNodeData(), false);
+                if (field.getKind() == FieldKind.CHILDREN) {
+                    spec.setCardinality(Cardinality.MULTIPLE);
+                    spec.setIndexed(true);
+                }
+                defaultParameters.add(spec);
             } else if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) {
                 String valueName = field.getName();
                 if (shortCircuitName != null && valueName.equals(shortCircuitName)) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Mon Feb 25 20:54:33 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Fri Mar 01 17:03:57 2013 +0100
@@ -80,31 +80,17 @@
         return name;
     }
 
-    private static String valueName(NodeFieldData field) {
-        return field.getName() + "Value";
-    }
-
     private static String valueName(ActualParameter param) {
-        NodeData node = (NodeData) param.getMethod().getTemplate();
-        NodeFieldData field = node.findField(param.getSpecification().getName());
-        if (field != null) {
-            return valueName(field);
-        } else {
-            return param.getSpecification().getName();
-        }
+        return param.getName();
     }
 
     private static String castValueName(ActualParameter parameter) {
         return valueName(parameter) + "Cast";
     }
 
-    private static String castValueName(NodeFieldData field) {
-        return valueName(field) + "Cast";
-    }
-
     private void addValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame) {
-        if (forceFrame) {
-            method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frame"));
+        if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
+            method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
         }
         for (ActualParameter parameter : specialization.getParameters()) {
             ParameterSpec spec = parameter.getSpecification();
@@ -116,8 +102,8 @@
     }
 
     private static void addValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame) {
-        if (forceFrame) {
-            builder.string("frame");
+        if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
+            builder.string("frameValue");
         }
         for (ActualParameter parameter : specialization.getParameters()) {
             ParameterSpec spec = parameter.getSpecification();
@@ -125,7 +111,7 @@
                 continue;
             }
 
-            if (unexpectedValueName != null && spec.getName().equals(unexpectedValueName)) {
+            if (unexpectedValueName != null && parameter.getName().equals(unexpectedValueName)) {
                 builder.string("ex.getResult()");
             } else {
                 builder.string(valueName(parameter));
@@ -138,7 +124,7 @@
         TypeSystemData typeSystem = node.getTypeSystem();
 
         for (ActualParameter targetParameter : targetSpecialization.getParameters()) {
-            ActualParameter valueParameter = valueSpecialization.findParameter(targetParameter.getSpecification().getName());
+            ActualParameter valueParameter = valueSpecialization.findParameter(targetParameter.getName());
             TypeData targetType = targetParameter.getActualTypeData(typeSystem);
 
             TypeData valueType = null;
@@ -276,13 +262,14 @@
     }
 
     private CodeTree createCasts(CodeTreeBuilder parent, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
-        NodeData node = guardedSpecialization.getNode();
-
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
         // Implict guards based on method signature
-        for (NodeFieldData field : node.getFields()) {
-            ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName());
-            ActualParameter valueParam = valueSpecialization.findParameter(field.getName());
+        for (ActualParameter guardedParam : guardedSpecialization.getParameters()) {
+            NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName());
+            if (field == null) {
+                continue;
+            }
+            ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getName());
 
             CodeTree cast = createCast(parent, field, valueParam, guardedParam);
             if (cast == null) {
@@ -295,14 +282,15 @@
     }
 
     private CodeTree createImplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
-        NodeData node = guardedSpecialization.getNode();
-
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
         // Implict guards based on method signature
         String andOperator = conditionPrefix != null ? conditionPrefix + " && " : "";
-        for (NodeFieldData field : node.getFields()) {
-            ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName());
-            ActualParameter valueParam = valueSpecialization.findParameter(field.getName());
+        for (ActualParameter guardedParam : guardedSpecialization.getParameters()) {
+            NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName());
+            if (field == null) {
+                continue;
+            }
+            ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getName());
 
             CodeTree implicitGuard = createImplicitGuard(builder, field, valueParam, guardedParam);
             if (implicitGuard == null) {
@@ -339,7 +327,7 @@
         }
 
         startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getActualTypeData(node.getTypeSystem())));
-        builder.string(valueName(field));
+        builder.string(valueName(source));
         builder.end().end(); // call
 
         if (field.isShortCircuit()) {
@@ -371,7 +359,7 @@
 
         CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), valueName(target));
 
-        return createLazyAssignment(parent, castValueName(field), target.getActualType(), condition, value);
+        return createLazyAssignment(parent, castValueName(target), target.getActualType(), condition, value);
     }
 
     /**
@@ -981,7 +969,7 @@
                 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod());
                 if (method.getParameters().size() == 1) {
                     CodeVariableElement var = CodeVariableElement.clone(method.getParameters().get(0));
-                    var.setName("frame");
+                    var.setName("frameValue");
                     method.getParameters().set(0, var);
                 }
                 method.getModifiers().remove(Modifier.ABSTRACT);
@@ -996,7 +984,7 @@
             }
 
             if (node.needsRewrites(getContext()) && !specialization.isGeneric() && !specialization.isUninitialized()) {
-                buildSpecializeStateMethod(clazz, specialization);
+                buildSpecializeAndExecute(clazz, specialization);
             }
         }
 
@@ -1014,7 +1002,7 @@
             CodeTree primaryExecuteCall = null;
 
             CodeTreeBuilder executeBuilder = CodeTreeBuilder.createBuilder();
-            buildExecute(executeBuilder, null, execType);
+            buildExecute(executeBuilder, null, null, execType);
             primaryExecuteCall = executeBuilder.getRoot();
 
             if (needsTry) {
@@ -1168,17 +1156,16 @@
 
         private CodeTree createExecuteChildren(CodeTreeBuilder parent, SpecializationData specialization) {
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            for (NodeFieldData field : specialization.getNode().getFields()) {
-                if (field.getExecutionKind() == ExecutionKind.IGNORE) {
+            for (ActualParameter parameter : specialization.getParameters()) {
+                NodeFieldData field = specialization.getNode().findField(parameter.getSpecification().getName());
+                if (field == null) {
                     continue;
                 }
 
-                ActualParameter parameterType = specialization.findParameter(field.getName());
-
-                if (parameterType.getActualTypeData(specialization.getNode().getTypeSystem()).isGeneric()) {
-                    buildGenericValueExecute(builder, specialization, field, null);
+                if (parameter.getActualTypeData(specialization.getNode().getTypeSystem()).isGeneric()) {
+                    buildGenericValueExecute(builder, specialization, parameter, field, null);
                 } else {
-                    buildSpecializedValueExecute(builder, specialization, field);
+                    buildSpecializedValueExecute(builder, specialization, parameter, field);
                 }
             }
             return builder.getRoot();
@@ -1194,10 +1181,9 @@
             }
         }
 
-        private void buildGenericValueExecute(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData field, NodeFieldData exceptionSpec) {
-            ActualParameter specParameter = specialization.findParameter(field.getName());
+        private void buildGenericValueExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field, ActualParameter exceptionParam) {
             NodeData node = specialization.getNode();
-            boolean shortCircuit = startShortCircuit(builder, specialization, field, exceptionSpec);
+            boolean shortCircuit = startShortCircuit(builder, specialization, param, exceptionParam);
 
             builder.startStatement();
             if (!shortCircuit) {
@@ -1205,19 +1191,19 @@
                 builder.string(" ");
             }
 
-            builder.string(valueName(specParameter));
+            builder.string(valueName(param));
             builder.string(" = ");
-            ExecutableTypeData genericExecutableType = field.getNodeData().findGenericExecutableType(getContext(), specParameter.getActualTypeData(node.getTypeSystem()));
+            ExecutableTypeData genericExecutableType = field.getNodeData().findGenericExecutableType(getContext(), param.getActualTypeData(node.getTypeSystem()));
             if (genericExecutableType == null) {
                 throw new AssertionError("Must have generic executable type. Parser validation most likely failed. " + Arrays.toString(field.getNodeData().getExecutableTypes()));
             }
-            buildExecute(builder, field, genericExecutableType);
+            buildExecute(builder, param, field, genericExecutableType);
             builder.end();
 
             endShortCircuit(builder, shortCircuit);
         }
 
-        private void buildExecute(CodeTreeBuilder builder, NodeFieldData field, ExecutableTypeData execType) {
+        private void buildExecute(CodeTreeBuilder builder, ActualParameter parameter, NodeFieldData field, ExecutableTypeData execType) {
             if (field != null) {
                 Element accessElement = field.getAccessElement();
                 if (accessElement.getKind() == ElementKind.METHOD) {
@@ -1227,18 +1213,20 @@
                 } else {
                     throw new AssertionError();
                 }
+                if (parameter.getSpecification().isIndexed()) {
+                    builder.string("[" + parameter.getIndex() + "]");
+                }
                 builder.string(".");
             }
             builder.startCall(execType.getMethodName());
             if (execType.getParameters().length == 1) {
-                builder.string("frame");
+                builder.string("frameValue");
             }
             builder.end();
         }
 
-        private void buildSpecializedValueExecute(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData field) {
-            ActualParameter param = specialization.findParameter(field.getName());
-            boolean shortCircuit = startShortCircuit(builder, specialization, field, null);
+        private void buildSpecializedValueExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field) {
+            boolean shortCircuit = startShortCircuit(builder, specialization, param, null);
 
             if (!shortCircuit) {
                 builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).end();
@@ -1250,24 +1238,26 @@
                 builder.startTryBlock();
             }
 
-            builder.startStatement().string(valueName(field)).string(" = ");
-            buildExecute(builder, field, execType);
+            builder.startStatement().string(valueName(param)).string(" = ");
+            buildExecute(builder, param, field, execType);
             builder.end();
 
             if (execType.hasUnexpectedValue(getContext())) {
                 builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
+                SpecializationData generic = specialization.getNode().getGenericSpecialization();
                 boolean execute = false;
-                for (NodeFieldData exField : specialization.getNode().getFields()) {
-                    if (exField.getExecutionKind() == ExecutionKind.IGNORE) {
+                for (ActualParameter exParam : generic.getParameters()) {
+                    NodeFieldData exField = generic.getNode().findField(exParam.getSpecification().getName());
+                    if (exField == null) {
                         continue;
                     }
                     if (execute) {
-                        buildGenericValueExecute(builder, specialization.getNode().getGenericSpecialization(), exField, field);
-                    } else if (exField == field) {
+                        buildGenericValueExecute(builder, specialization.getNode().getGenericSpecialization(), exParam, exField, param);
+                    } else if (exParam.getName().equals(param.getName())) {
                         execute = true;
                     }
                 }
-                builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param.getSpecification()));
+                builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param));
                 builder.end(); // catch block
             }
 
@@ -1275,12 +1265,16 @@
             builder.newLine();
         }
 
-        private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData forField, NodeFieldData exceptionField) {
+        private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) {
+            NodeFieldData forField = specialization.getNode().findField(parameter.getSpecification().getName());
+            if (forField == null) {
+                return false;
+            }
+
             if (forField.getExecutionKind() != ExecutionKind.SHORT_CIRCUIT) {
                 return false;
             }
 
-            ActualParameter parameter = specialization.findParameter(forField.getName());
             ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter);
 
             int shortCircuitIndex = 0;
@@ -1297,13 +1291,13 @@
             ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex];
 
             startCallOperationMethod(builder, shortCircuitData);
-            addValueParameterNames(builder, shortCircuitData, exceptionField != null ? exceptionField.getName() : null, false);
+            addValueParameterNames(builder, shortCircuitData, exceptionParam != null ? exceptionParam.getName() : null, false);
             builder.end().end(); // call operation
 
             builder.end(); // statement
 
             builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType()));
-            builder.startIf().string(shortCircuitParam.getSpecification().getName()).end();
+            builder.startIf().string(shortCircuitParam.getName()).end();
             builder.startBlock();
 
             return true;
@@ -1315,11 +1309,11 @@
             }
         }
 
-        private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) {
+        private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ActualParameter exceptionParam) {
             CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
             specializeCall.startCall("specializeAndExecute");
             specializeCall.string(nodeClassName(nextSpecialization) + ".class");
-            addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionSpec != null ? exceptionSpec.getName() : null, true);
+            addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getName() : null, true);
             specializeCall.end().end();
 
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
@@ -1329,7 +1323,7 @@
             return builder.getRoot();
         }
 
-        private void buildSpecializeStateMethod(CodeTypeElement clazz, SpecializationData specialization) {
+        private void buildSpecializeAndExecute(CodeTypeElement clazz, SpecializationData specialization) {
             NodeData node = specialization.getNode();
             TypeData returnType = specialization.getReturnType().getActualTypeData(node.getTypeSystem());
             ExecutableTypeData returnExecutableType = node.findExecutableType(returnType);
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java	Mon Feb 25 20:54:33 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java	Fri Mar 01 17:03:57 2013 +0100
@@ -71,6 +71,15 @@
         return !noSpecialization;
     }
 
+    public boolean supportsFrame() {
+        for (ExecutableTypeData execType : executableTypes) {
+            if (execType.findParameter("frameValue") == null) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     public List<NodeData> getNodeChildren() {
         List<NodeData> children = new ArrayList<>();
         for (NodeData child : getDeclaredChildren()) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java	Mon Feb 25 20:54:33 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java	Fri Mar 01 17:03:57 2013 +0100
@@ -28,7 +28,7 @@
 public class NodeFieldData {
 
     public enum FieldKind {
-        FIELD, CHILD, CHILDREN
+        CHILD, CHILDREN
     }
 
     public enum ExecutionKind {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Mon Feb 25 20:54:33 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Fri Mar 01 17:03:57 2013 +0100
@@ -208,6 +208,11 @@
             specialization.setNode(nodeData);
         }
 
+        // verify specialization parameter length
+        if (!verifySpecializationParameters(specializations)) {
+            return null;
+        }
+
         // verify order is not ambiguous
         if (!verifySpecializationOrder(typeSystem, specializations)) {
             return null;
@@ -247,6 +252,30 @@
         return nodeData;
     }
 
+    private boolean verifySpecializationParameters(List<SpecializationData> specializations) {
+        boolean valid = true;
+        int args = -1;
+        for (SpecializationData specializationData : specializations) {
+            int specializationArgs = 0;
+            for (ActualParameter param : specializationData.getParameters()) {
+                if (!param.getSpecification().isOptional()) {
+                    specializationArgs++;
+                }
+            }
+            if (args != -1 && args != specializationArgs) {
+                valid = false;
+                break;
+            }
+            args = specializationArgs;
+        }
+        if (!valid) {
+            for (SpecializationData specialization : specializations) {
+                context.getLog().error(specialization.getMethod(), specialization.getMarkerAnnotation(), "All specializations must have the same number of arguments.");
+            }
+        }
+        return valid;
+    }
+
     private boolean verifyMissingAbstractMethods(NodeData nodeData, List<Element> elements) {
         if (nodeData.needsFactory()) {
             // missing abstract methods only needs to be implemented
@@ -424,10 +453,10 @@
             nodeType = getComponentType(var.asType());
             kind = FieldKind.CHILDREN;
         } else {
-            mirror = null;
+            execution = ExecutionKind.IGNORE;
             nodeType = null;
-            kind = FieldKind.FIELD;
-            execution = ExecutionKind.IGNORE;
+            mirror = null;
+            kind = null;
         }
 
         NodeData fieldNodeData = null;
@@ -444,13 +473,12 @@
                 context.getLog().error(errorElement, "No executable generic types found for node '%s'.", Utils.getQualifiedName(nodeType));
                 return null;
             }
+
+            // TODO correct handling of access elements
+            if (var.getModifiers().contains(Modifier.PRIVATE) && Utils.typeEquals(var.getEnclosingElement().asType(), parentNodeData.getTemplateType().asType())) {
+                execution = ExecutionKind.IGNORE;
+            }
         }
-
-        // TODO correct handling of access elements
-        if (var.getModifiers().contains(Modifier.PRIVATE) && Utils.typeEquals(var.getEnclosingElement().asType(), parentNodeData.getTemplateType().asType())) {
-            execution = ExecutionKind.IGNORE;
-        }
-
         return new NodeFieldData(fieldNodeData, var, findAccessElement(var), mirror, kind, execution);
     }
 
@@ -617,9 +645,9 @@
     }
 
     private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) {
-        for (NodeFieldData field : node.getFields()) {
-            ActualParameter parameter = method.findParameter(field.getName());
-            if (parameter == null) {
+        for (ActualParameter parameter : method.getParameters()) {
+            NodeFieldData field = node.findField(parameter.getSpecification().getName());
+            if (field == null) {
                 continue;
             }
             ExecutableTypeData found = null;
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java	Mon Feb 25 20:54:33 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java	Fri Mar 01 17:03:57 2013 +0100
@@ -61,8 +61,7 @@
         }
 
         for (ActualParameter param : getParameters()) {
-            ParameterSpec paramSpec = param.getSpecification();
-            ActualParameter specializationParam = specialization.findParameter(paramSpec.getName());
+            ActualParameter specializationParam = specialization.findParameter(param.getName());
             if (!Utils.typeEquals(param.getActualType(), specializationParam.getActualType())) {
                 return false;
             }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java	Mon Feb 25 20:54:33 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java	Fri Mar 01 17:03:57 2013 +0100
@@ -31,10 +31,27 @@
     private final ParameterSpec specification;
     private final TypeMirror actualType;
     private TemplateMethod method;
+    private final String name;
+    private final int index;
 
-    public ActualParameter(ParameterSpec specification, TypeMirror actualType) {
+    public ActualParameter(ParameterSpec specification, TypeMirror actualType, int index) {
         this.specification = specification;
         this.actualType = actualType;
+
+        this.index = index;
+        String valueName = specification.getName() + "Value";
+        if (specification.isIndexed()) {
+            valueName = valueName + index;
+        }
+        this.name = valueName;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public String getName() {
+        return name;
     }
 
     void setMethod(TemplateMethod method) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java	Mon Feb 25 20:54:33 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java	Fri Mar 01 17:03:57 2013 +0100
@@ -41,4 +41,14 @@
     public List<ParameterSpec> getParameters() {
         return parameters;
     }
+
+    public ParameterSpec findParameterSpec(String name) {
+        for (ParameterSpec spec : parameters) {
+            if (spec.getName().equals(name)) {
+                return spec;
+            }
+        }
+        return null;
+    }
+
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java	Mon Feb 25 20:54:33 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java	Fri Mar 01 17:03:57 2013 +0100
@@ -39,7 +39,8 @@
     private final String name;
     private final TypeMirror[] allowedTypes;
     private final boolean optional;
-    private final Cardinality cardinality;
+    private Cardinality cardinality;
+    private boolean indexed;
 
     public ParameterSpec(String name, TypeMirror[] allowedTypes, boolean optional, Cardinality cardinality) {
         this.allowedTypes = allowedTypes;
@@ -63,6 +64,18 @@
         this(name, nodeTypeMirrors(nodeData), optional, cardinality);
     }
 
+    public boolean isIndexed() {
+        return indexed;
+    }
+
+    public void setIndexed(boolean indexed) {
+        this.indexed = indexed;
+    }
+
+    public void setCardinality(Cardinality cardinality) {
+        this.cardinality = cardinality;
+    }
+
     private static TypeMirror[] nodeTypeMirrors(NodeData nodeData) {
         Set<TypeMirror> typeMirrors = new LinkedHashSet<>();
 
@@ -95,6 +108,7 @@
         for (int i = 0; i < allowedTypes.length; i++) {
             TypeMirror mirror = allowedTypes[i];
             if (Utils.typeEquals(actualType, mirror)) {
+
                 return true;
             }
         }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java	Mon Feb 25 20:54:33 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java	Fri Mar 01 17:03:57 2013 +0100
@@ -70,7 +70,7 @@
 
     public ActualParameter findParameter(String valueName) {
         for (ActualParameter param : getParameters()) {
-            if (param.getSpecification().getName().equals(valueName)) {
+            if (param.getName().equals(valueName)) {
                 return param;
             }
         }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java	Mon Feb 25 20:54:33 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java	Fri Mar 01 17:03:57 2013 +0100
@@ -101,7 +101,7 @@
                 continue;
             }
 
-            E parsedMethod = parse(method, mirror);
+            E parsedMethod = parseNew(method, mirror);
             if (parsedMethod != null) {
                 parsedMethods.add(parsedMethod);
             } else {
@@ -114,7 +114,7 @@
         return parsedMethods;
     }
 
-    private E parse(ExecutableElement method, AnnotationMirror annotation) {
+    private E parseNew(ExecutableElement method, AnnotationMirror annotation) {
         MethodSpec methodSpecification = createSpecification(method, annotation);
         if (methodSpecification == null) {
             return null;
@@ -126,7 +126,7 @@
         List<ParameterSpec> parameterSpecs = new ArrayList<>();
         parameterSpecs.addAll(methodSpecification.getParameters());
 
-        ActualParameter returnTypeMirror = resolveTypeMirror(returnTypeSpec, method.getReturnType(), template);
+        ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0);
         if (returnTypeMirror == null) {
             if (isEmitErrors()) {
                 String expectedReturnType = createTypeSignature(returnTypeSpec, typeDefs, true);
@@ -140,88 +140,65 @@
             return null;
         }
 
-        Iterator<? extends VariableElement> variableIterator = method.getParameters().iterator();
+        List<ActualParameter> parameters = parseParameters(method, parameterSpecs);
+        if (parameters == null) {
+            if (isEmitErrors()) {
+                String message = String.format("Method signature mismatch. Expected signature: \n%s",
+                                createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
+                context.getLog().error(method, annotation, message);
+            }
+            return null;
+        }
+        ActualParameter[] paramMirrors = parameters.toArray(new ActualParameter[parameters.size()]);
+        return create(new TemplateMethod(template, methodSpecification, method, annotation, returnTypeMirror, paramMirrors));
+    }
+
+    private List<ActualParameter> parseParameters(ExecutableElement method, List<ParameterSpec> parameterSpecs) {
+        Iterator<? extends VariableElement> parameterIterator = 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()) {
-                    if (isEmitErrors()) {
-                        // non option type specification found -> argument missing
-                        String expectedType = createTypeSignature(specification, typeDefs, false);
-
-                        String message = String.format("Missing argument \"%s\".\nExpected signature: \n %s", expectedType,
-                                        createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
+        VariableElement parameter = parameterIterator.hasNext() ? parameterIterator.next() : null;
+        ParameterSpec specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
 
-                        context.getLog().error(method, message);
-                    }
-                    return null;
-                } else {
-                    // specification is optional -> continue
-                    specification = null;
+        int specificationIndex = 0;
+        List<ActualParameter> resolvedParameters = new ArrayList<>();
+        while (parameter != null || specification != null) {
+            if (parameter == null || specification == null) {
+                if (specification != null && (specification.isOptional() || specification.getCardinality() == Cardinality.MULTIPLE)) {
+                    specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
+                    specificationIndex = 0;
                     continue;
                 }
-            }
-
-            ActualParameter resolvedMirror = resolveTypeMirror(specification, parameter.asType(), template);
-
-            if (resolvedMirror == null) {
-                if (specification.isOptional()) {
-                    specification = null;
-                    continue;
-                }
-
-                if (isEmitErrors()) {
-                    String expectedReturnType = createTypeSignature(specification, typeDefs, 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, typeDefs));
-
-                    context.getLog().error(parameter, message);
-                }
                 return null;
             }
 
-            resolvedMirrors.add(resolvedMirror);
-            parameter = null; // consume parameter
+            ActualParameter resolvedParameter = matchParameter(specification, parameter.asType(), template, specificationIndex);
+            if (resolvedParameter == null) {
+                // mismatch
+                if (specification.isOptional()) {
+                    specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
+                    specificationIndex = 0;
+                } else {
+                    return null;
+                }
+            } else {
+                resolvedParameters.add(resolvedParameter);
 
-            if (specification.getCardinality() != Cardinality.MULTIPLE) {
-                specification = null;
+                // match
+                if (specification.getCardinality() == Cardinality.ONE) {
+                    parameter = parameterIterator.hasNext() ? parameterIterator.next() : null;
+                    specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
+                    specificationIndex = 0;
+                } else if (specification.getCardinality() == Cardinality.MULTIPLE) {
+                    parameter = parameterIterator.hasNext() ? parameterIterator.next() : null;
+                    specificationIndex++;
+                }
             }
         }
-
-        if (variableIterator.hasNext()) {
-            parameter = variableIterator.next();
-            if (isEmitErrors()) {
-                String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName();
-                String message = String.format("No argument expected but found \"%s\".\nExpected signature: \n %s", actualReturnType,
-                                createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
-
-                context.getLog().error(parameter, message);
-            }
-            return null;
-        }
-
-        ActualParameter[] paramMirrors = resolvedMirrors.toArray(new ActualParameter[resolvedMirrors.size()]);
-        return create(new TemplateMethod(template, methodSpecification, method, annotation, returnTypeMirror, paramMirrors));
+        return resolvedParameters;
     }
 
-    private ActualParameter resolveTypeMirror(ParameterSpec specification, TypeMirror mirror, Template typeSystem) {
+    private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template typeSystem, int index) {
         TypeMirror resolvedType = mirror;
         if (hasError(resolvedType)) {
             resolvedType = context.resolveNotYetCompiledType(mirror, typeSystem);
@@ -230,7 +207,7 @@
         if (!specification.matches(resolvedType)) {
             return null;
         }
-        return new ActualParameter(specification, resolvedType);
+        return new ActualParameter(specification, resolvedType, index);
     }
 
     protected List<TypeDef> createTypeDefinitions(ParameterSpec returnType, List<? extends ParameterSpec> parameters) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java	Mon Feb 25 20:54:33 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java	Fri Mar 01 17:03:57 2013 +0100
@@ -54,7 +54,7 @@
     @Override
     public TypeCastData create(TemplateMethod method) {
         TypeData targetType = findTypeByMethodName(method.getMethod(), method.getMarkerAnnotation(), "as");
-        ActualParameter parameter = method.findParameter("value");
+        ActualParameter parameter = method.findParameter("valueValue");
         return new TypeCastData(method, parameter.getActualTypeData(getTypeSystem()), targetType);
     }
 
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java	Mon Feb 25 20:54:33 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java	Fri Mar 01 17:03:57 2013 +0100
@@ -55,7 +55,7 @@
     public TypeCheckData create(TemplateMethod method) {
         TypeData checkedType = findTypeByMethodName(method.getMethod(), method.getMarkerAnnotation(), "is");
         assert checkedType != null;
-        ActualParameter parameter = method.findParameter("value");
+        ActualParameter parameter = method.findParameter("valueValue");
         assert parameter != null;
         return new TypeCheckData(method, checkedType, parameter.getActualTypeData(getTypeSystem()));
     }