diff graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java @ 19289:62c43fcf5be2

Truffle-DSL: implement @Cached and fixes for the new guard expression syntax.
author Christian Humer <christian.humer@gmail.com>
date Tue, 03 Feb 2015 15:07:07 +0100
parents 08aa0372dad4
children 18c0f02fa4d2
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java	Mon Dec 29 18:32:03 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java	Tue Feb 03 15:07:07 2015 +0100
@@ -30,6 +30,7 @@
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
 import com.oracle.truffle.dsl.processor.model.*;
 
 public final class MethodSpecParser {
@@ -76,26 +77,13 @@
 
         String id = method.getSimpleName().toString();
         TypeMirror returnType = method.getReturnType();
-        List<TypeMirror> parameterTypes = new ArrayList<>();
-        for (VariableElement var : method.getParameters()) {
-            parameterTypes.add(var.asType());
-        }
-
-        TemplateMethod templateMethod = parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, parameterTypes);
-        if (templateMethod != null) {
-            for (int i = 0; i < templateMethod.getParameters().size(); i++) {
-                if (i < method.getParameters().size()) {
-                    templateMethod.getParameters().get(i).setVariableElement(method.getParameters().get(i));
-                }
-            }
-        }
-        return templateMethod;
+        return parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, method.getParameters());
     }
 
     public TemplateMethod parseImpl(MethodSpec methodSpecification, int naturalOrder, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType,
-                    List<TypeMirror> parameterTypes) {
+                    List<? extends VariableElement> parameterTypes) {
         ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
-        Parameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, -1, -1);
+        Parameter returnTypeMirror = matchParameter(returnTypeSpec, new CodeVariableElement(returnType, "returnType"), -1, -1);
         if (returnTypeMirror == null) {
             if (emitErrors) {
                 TemplateMethod invalidMethod = new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<Parameter> emptyList());
@@ -147,11 +135,11 @@
      * end matching the required arguments, parsing fails. Parameters prior to the parsed required
      * ones are cut and used to parse the optional parameters.
      */
-    private List<Parameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes, boolean varArgs) {
+    private List<Parameter> parseParameters(MethodSpec spec, List<? extends VariableElement> parameterTypes, boolean varArgs) {
         List<Parameter> parsedRequired = null;
         int offset = 0;
         for (; offset <= parameterTypes.size(); offset++) {
-            List<TypeMirror> parameters = new ArrayList<>();
+            List<VariableElement> parameters = new ArrayList<>();
             parameters.addAll(parameterTypes.subList(offset, parameterTypes.size()));
             parsedRequired = parseParametersRequired(spec, parameters, varArgs);
             if (parsedRequired != null) {
@@ -166,7 +154,7 @@
         if (parsedRequired.isEmpty() && offset == 0) {
             offset = parameterTypes.size();
         }
-        List<TypeMirror> potentialOptionals = parameterTypes.subList(0, offset);
+        List<? extends VariableElement> potentialOptionals = parameterTypes.subList(0, offset);
         List<Parameter> parsedOptionals = parseParametersOptional(spec, potentialOptionals);
         if (parsedOptionals == null) {
             return null;
@@ -178,7 +166,7 @@
         return finalParameters;
     }
 
-    private List<Parameter> parseParametersOptional(MethodSpec spec, List<TypeMirror> types) {
+    private List<Parameter> parseParametersOptional(MethodSpec spec, List<? extends VariableElement> types) {
         List<Parameter> parsedParams = new ArrayList<>();
 
         int typeStartIndex = 0;
@@ -186,8 +174,8 @@
         outer: for (int specIndex = 0; specIndex < specifications.size(); specIndex++) {
             ParameterSpec specification = specifications.get(specIndex);
             for (int typeIndex = typeStartIndex; typeIndex < types.size(); typeIndex++) {
-                TypeMirror actualType = types.get(typeIndex);
-                Parameter optionalParam = matchParameter(specification, actualType, -1, -1);
+                VariableElement variable = types.get(typeIndex);
+                Parameter optionalParam = matchParameter(specification, variable, -1, -1);
                 if (optionalParam != null) {
                     parsedParams.add(optionalParam);
                     typeStartIndex = typeIndex + 1;
@@ -203,7 +191,7 @@
         return parsedParams;
     }
 
-    private List<Parameter> parseParametersRequired(MethodSpec spec, List<TypeMirror> types, boolean typeVarArgs) {
+    private List<Parameter> parseParametersRequired(MethodSpec spec, List<VariableElement> types, boolean typeVarArgs) {
         List<Parameter> parsedParams = new ArrayList<>();
         List<ParameterSpec> specifications = spec.getRequired();
         boolean specVarArgs = spec.isVariableRequiredParameters();
@@ -212,7 +200,7 @@
 
         ParameterSpec specification;
         while ((specification = nextSpecification(specifications, specificationIndex, specVarArgs)) != null) {
-            TypeMirror actualType = nextActualType(types, typeIndex, typeVarArgs);
+            VariableElement actualType = nextActualType(types, typeIndex, typeVarArgs);
             if (actualType == null) {
                 if (spec.isIgnoreAdditionalSpecifications()) {
                     break;
@@ -238,8 +226,18 @@
             specificationIndex++;
         }
 
+        // consume randomly ordered annotated parameters
+        VariableElement variable;
+        while ((variable = nextActualType(types, typeIndex, typeVarArgs)) != null) {
+            Parameter matchedParamter = matchAnnotatedParameter(spec, variable);
+            if (matchedParamter == null) {
+                break;
+            }
+            parsedParams.add(matchedParamter);
+            typeIndex++;
+        }
+
         if (typeIndex < types.size()) {
-            // additional types available
             if (spec.isIgnoreAdditionalParameters()) {
                 return parsedParams;
             } else {
@@ -250,6 +248,19 @@
         return parsedParams;
     }
 
+    private Parameter matchAnnotatedParameter(MethodSpec spec, VariableElement variable) {
+        for (ParameterSpec parameterSpec : spec.getAnnotations()) {
+            if (parameterSpec.matches(variable)) {
+                Parameter matchedParameter = matchParameter(parameterSpec, variable, -1, -1);
+                if (matchedParameter != null) {
+                    matchedParameter.setLocalName(variable.getSimpleName().toString());
+                    return matchedParameter;
+                }
+            }
+        }
+        return null;
+    }
+
     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);
@@ -260,12 +271,12 @@
         }
     }
 
-    private static TypeMirror nextActualType(List<TypeMirror> types, int typeIndex, boolean varArgs) {
+    private static VariableElement nextActualType(List<VariableElement> 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();
+            VariableElement actualType = types.get(types.size() - 1);
+            if (actualType.asType().getKind() == TypeKind.ARRAY) {
+                actualType = new CodeVariableElement(((ArrayType) actualType.asType()).getComponentType(), actualType.getSimpleName().toString());
             }
             return actualType;
         } else if (typeIndex < types.size()) {
@@ -275,21 +286,21 @@
         }
     }
 
-    private Parameter matchParameter(ParameterSpec specification, TypeMirror mirror, int specificationIndex, int varArgsIndex) {
-        TypeMirror resolvedType = mirror;
+    private Parameter matchParameter(ParameterSpec specification, VariableElement variable, int specificationIndex, int varArgsIndex) {
+        TypeMirror resolvedType = variable.asType();
         if (hasError(resolvedType)) {
             return null;
         }
 
-        if (!specification.matches(resolvedType)) {
+        if (!specification.matches(variable)) {
             return null;
         }
 
         TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType);
         if (resolvedTypeData != null) {
-            return new Parameter(specification, resolvedTypeData, specificationIndex, varArgsIndex);
+            return new Parameter(specification, resolvedTypeData, variable, specificationIndex, varArgsIndex);
         } else {
-            return new Parameter(specification, resolvedType, specificationIndex, varArgsIndex);
+            return new Parameter(specification, variable, specificationIndex, varArgsIndex);
         }
     }