Mercurial > hg > graal-jvmci-8
diff graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java @ 13527:25ecb47a6d0e
Truffle-DSL: Added support for references to child arrays in @ShortCircuit;
Introduced new layer NodeExecutionData to the implementation model which is in between NodeChildData and the actual parameters..
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Tue, 07 Jan 2014 12:22:47 +0100 |
parents | e4862151eefd |
children | 5a0c694ef735 |
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java Thu Dec 26 12:37:28 2013 -0800 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java Tue Jan 07 12:22:47 2014 +0100 @@ -33,7 +33,6 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.node.NodeChildData.*; import com.oracle.truffle.dsl.processor.typesystem.*; public abstract class TemplateMethodParser<T extends Template, E extends TemplateMethod> { @@ -147,14 +146,23 @@ id = Utils.getAnnotationValue(String.class, idAnnotation, "value"); } - ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); + TypeMirror returnType = method.getReturnType(); + List<TypeMirror> parameterTypes = new ArrayList<>(); + for (VariableElement var : method.getParameters()) { + parameterTypes.add(var.asType()); + } - ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, -1, false); + return parseImpl(methodSpecification, id, method, annotation, returnType, parameterTypes); + } + + private E parseImpl(MethodSpec methodSpecification, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType, List<TypeMirror> parameterTypes) { + ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); + ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, template, -1, -1, false); if (returnTypeMirror == null) { if (emitErrors) { E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true); String expectedReturnType = returnTypeSpec.toSignatureString(true); - String actualReturnType = Utils.getSimpleName(method.getReturnType()); + String actualReturnType = Utils.getSimpleName(returnType); String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType, methodSpecification.toSignatureString(method.getSimpleName().toString())); @@ -165,12 +173,7 @@ } } - List<TypeMirror> parameterTypes = new ArrayList<>(); - for (VariableElement var : method.getParameters()) { - parameterTypes.add(var.asType()); - } - - List<ActualParameter> parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method.isVarArgs()); + List<ActualParameter> parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method != null ? method.isVarArgs() : false); if (parameters == null) { if (isEmitErrors()) { E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true); @@ -207,34 +210,31 @@ * Parameter parsing tries to parse required arguments starting from offset 0 with increasing * offset until it finds a signature end that matches the required specification. If there is no * end matching the required arguments, parsing fails. Parameters prior to the parsed required - * ones are cut and used to parse the optional parameters. All those remaining parameters must - * be consumed otherwise its an error. + * ones are cut and used to parse the optional parameters. */ private List<ActualParameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes, boolean varArgs) { List<TypeMirror> implicitTypes = spec.getImplicitRequiredTypes(); - int offset = -1; List<ActualParameter> parsedRequired = null; - ConsumableListIterator<TypeMirror> types = null; - while (parsedRequired == null && offset < parameterTypes.size()) { - offset++; - types = new ConsumableListIterator<>(new ArrayList<>(implicitTypes)); - types.data.addAll(parameterTypes.subList(offset, parameterTypes.size())); - parsedRequired = parseParametersRequired(spec, types, varArgs); + int offset = 0; + for (; offset <= parameterTypes.size(); offset++) { + List<TypeMirror> parameters = new ArrayList<>(implicitTypes); + parameters.addAll(parameterTypes.subList(offset, parameterTypes.size())); + parsedRequired = parseParametersRequired(spec, parameters, varArgs); + if (parsedRequired != null) { + break; + } } - if (parsedRequired == null && offset >= 0) { + if (parsedRequired == null) { return null; } - List<TypeMirror> potentialOptionals; - if (offset == -1) { - potentialOptionals = parameterTypes; - } else { - potentialOptionals = parameterTypes.subList(0, offset); + if (parsedRequired.isEmpty() && offset == 0) { + offset = parameterTypes.size(); } - types = new ConsumableListIterator<>(potentialOptionals); - List<ActualParameter> parsedOptionals = parseParametersOptional(spec, types); + List<TypeMirror> potentialOptionals = parameterTypes.subList(0, offset); + List<ActualParameter> parsedOptionals = parseParametersOptional(spec, potentialOptionals); if (parsedOptionals == null) { return null; } @@ -245,99 +245,105 @@ return finalParameters; } - private List<ActualParameter> parseParametersOptional(MethodSpec spec, ConsumableListIterator<TypeMirror> types) { + private List<ActualParameter> parseParametersOptional(MethodSpec spec, List<TypeMirror> types) { List<ActualParameter> parsedParams = new ArrayList<>(); - // parse optional parameters - ConsumableListIterator<ParameterSpec> optionals = new ConsumableListIterator<>(spec.getOptional()); - for (TypeMirror type : types) { - int oldIndex = types.getIndex(); - int optionalCount = 1; - for (ParameterSpec paramspec : optionals) { - ActualParameter optionalParam = matchParameter(paramspec, type, template, 0, -1, false); + + int typeStartIndex = 0; + List<ParameterSpec> specifications = spec.getOptional(); + outer: for (int specIndex = 0; specIndex < specifications.size(); specIndex++) { + ParameterSpec specification = specifications.get(specIndex); + for (int typeIndex = typeStartIndex; typeIndex < types.size(); typeIndex++) { + TypeMirror actualType = types.get(typeIndex); + ActualParameter optionalParam = matchParameter(specification, actualType, template, -1, -1, false); if (optionalParam != null) { - optionals.consume(optionalCount); - types.consume(); parsedParams.add(optionalParam); - break; + typeStartIndex = typeIndex + 1; + continue outer; } - optionalCount++; - } - if (oldIndex == types.getIndex()) { - // nothing found anymore skip optional - break; } } - if (types.getIndex() <= types.data.size() - 1) { + + if (typeStartIndex < types.size()) { + // not enough types found return null; } return parsedParams; } - private List<ActualParameter> parseParametersRequired(MethodSpec spec, ConsumableListIterator<TypeMirror> types, boolean varArgs) { + private List<ActualParameter> parseParametersRequired(MethodSpec spec, List<TypeMirror> types, boolean typeVarArgs) { List<ActualParameter> parsedParams = new ArrayList<>(); + List<ParameterSpec> specifications = spec.getRequired(); + boolean specVarArgs = spec.isVariableRequiredParameters(); + int typeIndex = 0; + int specificationIndex = 0; - int varArgsParameterIndex = -1; - int specificationParameterIndex = 0; - ConsumableListIterator<ParameterSpec> required = new ConsumableListIterator<>(spec.getRequired()); - while (required.get() != null || types.get() != null) { - if (required.get() == null || types.get() == null) { - if (required.get() != null && required.get().getCardinality() == Cardinality.MANY) { - required.consume(); - specificationParameterIndex = 0; - continue; + ParameterSpec specification; + while ((specification = nextSpecification(specifications, specificationIndex, specVarArgs)) != null) { + TypeMirror actualType = nextActualType(types, typeIndex, typeVarArgs); + if (actualType == null) { + if (spec.isIgnoreAdditionalSpecifications()) { + break; } + return null; + } + + boolean implicit = typeIndex < spec.getImplicitRequiredTypes().size(); + int typeVarArgsIndex = typeVarArgs ? typeIndex - types.size() + 1 : -1; + int specVarArgsIndex = specVarArgs ? specificationIndex - specifications.size() + 1 : -1; + + if (typeVarArgsIndex >= 0 && specVarArgsIndex >= 0) { + // both specifications and types have a variable number of arguments + // we would get into an endless loop if we would continue break; } - TypeMirror actualType = types.get(); - if (varArgs && types.isLast()) { - if (actualType.getKind() == TypeKind.ARRAY) { - actualType = ((ArrayType) actualType).getComponentType(); - } - varArgsParameterIndex++; + + ActualParameter resolvedParameter = matchParameter(specification, actualType, template, specVarArgsIndex, typeVarArgsIndex, implicit); + if (resolvedParameter == null) { + return null; } - boolean implicit = types.getIndex() < spec.getImplicitRequiredTypes().size(); - ActualParameter resolvedParameter = matchParameter(required.get(), actualType, template, specificationParameterIndex, varArgsParameterIndex, implicit); - if (resolvedParameter == null) { - if (required.get().getCardinality() == Cardinality.MANY) { - required.consume(); - continue; - } - // direct mismatch but required -> error - return null; + parsedParams.add(resolvedParameter); + typeIndex++; + specificationIndex++; + } + + if (typeIndex < types.size()) { + // additional types available + if (spec.isIgnoreAdditionalParameters()) { + return parsedParams; } else { - parsedParams.add(resolvedParameter); - - if (varArgs && types.isLast()) { - /* Both varargs spec and varargs definition. Need to consume to terminate. */ - if (required.get().getCardinality() == Cardinality.MANY) { - types.consume(); - } - } else { - types.consume(); - } - - if (required.get().getCardinality() == Cardinality.ONE) { - required.consume(); - specificationParameterIndex = 0; - } else if (required.get().getCardinality() == Cardinality.MANY) { - specificationParameterIndex++; - } + return null; } } - if (!types.toList().isEmpty() && !(varArgs && types.isLast())) { - // additional types -> error - return null; - } - - if (!required.toList().isEmpty() && !spec.isVariableRequiredArguments()) { - // additional specifications -> error - return null; - } return parsedParams; } - private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int specificationIndex, int varArgsIndex, boolean implicit) { + private static ParameterSpec nextSpecification(List<ParameterSpec> specifications, int specIndex, boolean varArgs) { + if (varArgs && specIndex >= specifications.size() - 1 && !specifications.isEmpty()) { + return specifications.get(specifications.size() - 1); + } else if (specIndex < specifications.size()) { + return specifications.get(specIndex); + } else { + return null; + } + } + + private static TypeMirror nextActualType(List<TypeMirror> types, int typeIndex, boolean varArgs) { + if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) { + // unpack varargs array argument + TypeMirror actualType = types.get(types.size() - 1); + if (actualType.getKind() == TypeKind.ARRAY) { + actualType = ((ArrayType) actualType).getComponentType(); + } + return actualType; + } else if (typeIndex < types.size()) { + return types.get(typeIndex); + } else { + return null; + } + } + + protected final ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int specificationIndex, int varArgsIndex, boolean implicit) { TypeMirror resolvedType = mirror; if (hasError(resolvedType)) { resolvedType = context.resolveNotYetCompiledType(mirror, originalTemplate); @@ -355,57 +361,7 @@ } } - /* Helper class for parsing. */ - private static class ConsumableListIterator<E> implements Iterable<E> { - - private final List<E> data; - private int index; - - public ConsumableListIterator(List<E> data) { - this.data = data; - } - - public E get() { - if (index >= data.size()) { - return null; - } - return data.get(index); - } - - public boolean isLast() { - return index == data.size() - 1; - } - - public E consume() { - return consume(1); - } - - public E consume(int count) { - if (index + count <= data.size()) { - index += count; - return get(); - } else { - throw new ArrayIndexOutOfBoundsException(count + 1); - } - } - - public int getIndex() { - return index; - } - - @Override - public Iterator<E> iterator() { - return toList().iterator(); - } - - public List<E> toList() { - if (index < data.size()) { - return data.subList(index, data.size()); - } else { - return Collections.<E> emptyList(); - } - } - + public final E create(String id, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List<TypeMirror> parameterTypes) { + return parseImpl(createSpecification(methodMetadata, mirror), id, methodMetadata, mirror, returnType, parameterTypes); } - }