# HG changeset patch # User Christian Humer # Date 1362153837 -3600 # Node ID 6b74ffe38183423a940a0ed6b53c880754d2a60a # Parent dbbdc0a30a163ac0829e5d4a283bb278099543ce Implemented support for executing nodes in @Children fields. diff -r dbbdc0a30a16 -r 6b74ffe38183 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java --- 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); } diff -r dbbdc0a30a16 -r 6b74ffe38183 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java --- 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 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)) { diff -r dbbdc0a30a16 -r 6b74ffe38183 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java --- 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); diff -r dbbdc0a30a16 -r 6b74ffe38183 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java --- 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 getNodeChildren() { List children = new ArrayList<>(); for (NodeData child : getDeclaredChildren()) { diff -r dbbdc0a30a16 -r 6b74ffe38183 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java --- 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 { diff -r dbbdc0a30a16 -r 6b74ffe38183 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java --- 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 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 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; diff -r dbbdc0a30a16 -r 6b74ffe38183 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java --- 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; } diff -r dbbdc0a30a16 -r 6b74ffe38183 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java --- 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) { diff -r dbbdc0a30a16 -r 6b74ffe38183 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java --- 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 getParameters() { return parameters; } + + public ParameterSpec findParameterSpec(String name) { + for (ParameterSpec spec : parameters) { + if (spec.getName().equals(name)) { + return spec; + } + } + return null; + } + } diff -r dbbdc0a30a16 -r 6b74ffe38183 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java --- 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 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; } } diff -r dbbdc0a30a16 -r 6b74ffe38183 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java --- 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; } } diff -r dbbdc0a30a16 -r 6b74ffe38183 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java --- 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 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 variableIterator = method.getParameters().iterator(); + List 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 parseParameters(ExecutableElement method, List parameterSpecs) { + Iterator parameterIterator = method.getParameters().iterator(); Iterator specificationIterator = parameterSpecs.iterator(); - List 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 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 createTypeDefinitions(ParameterSpec returnType, List parameters) { diff -r dbbdc0a30a16 -r 6b74ffe38183 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java --- 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); } diff -r dbbdc0a30a16 -r 6b74ffe38183 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java --- 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())); }