diff graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java @ 8595:8a1115c92271

Implemented codegen guard definitions can now omit unused parameters.
author Christian Humer <christian.humer@gmail.com>
date Mon, 01 Apr 2013 21:43:20 +0200
parents 2be3865d9ea0
children 61ba6fc21ba4
line wrap: on
line diff
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java	Mon Apr 01 21:43:20 2013 +0200
@@ -110,13 +110,7 @@
                 valid = false;
             }
         }
-        Collections.sort(parsedMethods, new Comparator<TemplateMethod>() {
-
-            @Override
-            public int compare(TemplateMethod o1, TemplateMethod o2) {
-                return o1.getMethodName().compareTo(o2.getMethodName());
-            }
-        });
+        Collections.sort(parsedMethods);
 
         if (!valid && parseNullOnError) {
             return null;
@@ -130,27 +124,25 @@
             return null;
         }
 
+        methodSpecification.applyTypeDefinitions("types");
+
         String id = method.getSimpleName().toString();
         AnnotationMirror idAnnotation = Utils.findAnnotationMirror(context.getEnvironment(), method, NodeId.class);
         if (idAnnotation != null) {
             id = Utils.getAnnotationValue(String.class, idAnnotation, "value");
         }
 
-        List<TypeDef> typeDefs = createTypeDefinitions(methodSpecification.getReturnType(), methodSpecification.getParameters());
-
         ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
-        List<ParameterSpec> parameterSpecs = new ArrayList<>();
-        parameterSpecs.addAll(methodSpecification.getParameters());
 
         ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, false);
         if (returnTypeMirror == null) {
             if (emitErrors) {
                 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()));
-                String expectedReturnType = createTypeSignature(returnTypeSpec, typeDefs, true);
+                String expectedReturnType = returnTypeSpec.toSignatureString(true);
                 String actualReturnType = Utils.getSimpleName(method.getReturnType());
 
                 String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
-                                createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
+                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
                 invalidMethod.addError(message);
                 return invalidMethod;
             } else {
@@ -163,12 +155,12 @@
             parameterTypes.add(var.asType());
         }
 
-        List<ActualParameter> parameters = parseParameters(parameterTypes, methodSpecification.getImplicitTypes(), parameterSpecs);
+        List<ActualParameter> parameters = parseParameters(methodSpecification, parameterTypes);
         if (parameters == null) {
             if (isEmitErrors()) {
                 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()));
                 String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method),
-                                createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
+                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
                 invalidMethod.addError(message);
                 return invalidMethod;
             } else {
@@ -180,87 +172,95 @@
     }
 
     private static String createActualSignature(MethodSpec spec, ExecutableElement method) {
-        List<String> types = new ArrayList<>();
-        for (TypeMirror implicitType : spec.getImplicitTypes()) {
-            types.add("implicit " + Utils.getSimpleName(implicitType));
+        StringBuilder b = new StringBuilder("(");
+        String sep = "";
+        for (TypeMirror implicitType : spec.getImplicitRequiredTypes()) {
+            b.append(sep);
+            b.append("implicit " + Utils.getSimpleName(implicitType));
+            sep = ", ";
         }
         for (VariableElement var : method.getParameters()) {
-            types.add(Utils.getSimpleName(var.asType()));
-        }
-
-        StringBuilder b = new StringBuilder("(");
-        for (Iterator<String> iterator = types.iterator(); iterator.hasNext();) {
-            b.append(iterator.next());
-            if (iterator.hasNext()) {
-                b.append(", ");
-            }
+            b.append(sep);
+            b.append(Utils.getSimpleName(var.asType()));
+            sep = ", ";
         }
         b.append(")");
         return b.toString();
     }
 
-    private List<ActualParameter> parseParameters(List<TypeMirror> types, List<TypeMirror> implicitTypes, List<ParameterSpec> parameterSpecs) {
-        Iterator<? extends TypeMirror> parameterIterator = types.iterator();
-        Iterator<? extends TypeMirror> implicitParametersIterator = implicitTypes.iterator();
-        Iterator<? extends ParameterSpec> specificationIterator = parameterSpecs.iterator();
+    private List<ActualParameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes) {
+        List<ActualParameter> parsedParams = new ArrayList<>();
+        ConsumableListIterator<TypeMirror> types = new ConsumableListIterator<>(parameterTypes);
 
-        TypeMirror parameter = parameterIterator.hasNext() ? parameterIterator.next() : null;
-        TypeMirror implicitParameter = implicitParametersIterator.hasNext() ? implicitParametersIterator.next() : null;
-        ParameterSpec specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
+        // 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, false);
+                if (optionalParam != null) {
+                    optionals.consume(optionalCount);
+                    types.consume();
+                    parsedParams.add(optionalParam);
+                    break;
+                }
+                optionalCount++;
+            }
+            if (oldIndex == types.getIndex()) {
+                // nothing found anymore skip optional
+                break;
+            }
+        }
+
+        List<TypeMirror> typesWithImplicit = new ArrayList<>(spec.getImplicitRequiredTypes());
+        typesWithImplicit.addAll(types.toList());
+        types = new ConsumableListIterator<>(typesWithImplicit);
 
         int specificationParameterIndex = 0;
-        List<ActualParameter> resolvedParameters = new ArrayList<>();
-        while (parameter != null || specification != null || implicitParameter != null) {
-            if (parameter == null || specification == null) {
-                if (specification != null && (specification.isOptional() || specification.getCardinality() == Cardinality.MULTIPLE)) {
-                    specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
+        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.MULTIPLE) {
+                    required.consume();
                     specificationParameterIndex = 0;
                     continue;
                 }
-                return null;
+                break;
             }
-
-            ActualParameter resolvedParameter = null;
-
-            boolean implicit = false;
-            if (implicitParameter != null) {
-                resolvedParameter = matchParameter(specification, implicitParameter, template, specificationParameterIndex, true);
-                if (resolvedParameter != null) {
-                    implicit = true;
-                }
-            }
-
-            if (resolvedParameter == null) {
-                resolvedParameter = matchParameter(specification, parameter, template, specificationParameterIndex, false);
-            }
-
+            boolean implicit = types.getIndex() < spec.getImplicitRequiredTypes().size();
+            ActualParameter resolvedParameter = matchParameter(required.get(), types.get(), template, specificationParameterIndex, implicit);
             if (resolvedParameter == null) {
-                // mismatch
-                if (specification.isOptional()) {
-                    specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
-                    specificationParameterIndex = 0;
-                } else {
-                    return null;
+                if (required.get().getCardinality() == Cardinality.MULTIPLE) {
+                    required.consume();
+                    continue;
                 }
+                // direct mismatch but required -> error
+                return null;
             } else {
-                resolvedParameters.add(resolvedParameter);
-
-                // match
-                if (implicit) {
-                    implicitParameter = implicitParametersIterator.hasNext() ? implicitParametersIterator.next() : null;
-                } else {
-                    parameter = parameterIterator.hasNext() ? parameterIterator.next() : null;
-                }
-
-                if (specification.getCardinality() == Cardinality.ONE) {
-                    specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
+                parsedParams.add(resolvedParameter);
+                types.consume();
+                if (required.get().getCardinality() == Cardinality.ONE) {
+                    required.consume();
                     specificationParameterIndex = 0;
-                } else if (specification.getCardinality() == Cardinality.MULTIPLE) {
+                } else if (required.get().getCardinality() == Cardinality.MULTIPLE) {
                     specificationParameterIndex++;
                 }
             }
         }
-        return resolvedParameters;
+
+        if (!types.toList().isEmpty()) {
+            // additional types -> error
+            return null;
+        }
+
+        if (!required.toList().isEmpty() && !spec.isVariableRequiredArguments()) {
+            // additional specifications -> error
+            return null;
+        }
+
+        // success!
+        return parsedParams;
     }
 
     private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template typeSystem, int index, boolean implicit) {
@@ -275,143 +275,53 @@
         return new ActualParameter(specification, resolvedType, index, implicit);
     }
 
-    protected List<TypeDef> createTypeDefinitions(ParameterSpec returnType, List<? extends ParameterSpec> parameters) {
-        List<TypeDef> typeDefs = new ArrayList<>();
+    /* Helper class for parsing. */
+    private static class ConsumableListIterator<E> implements Iterable<E> {
 
-        List<ParameterSpec> allParams = new ArrayList<>();
-        allParams.add(returnType);
-        allParams.addAll(parameters);
+        private final List<E> data;
+        private int index;
+
+        public ConsumableListIterator(List<E> data) {
+            this.data = data;
+        }
 
-        int defIndex = 0;
-        for (ParameterSpec spec : allParams) {
-            List<TypeMirror> allowedTypes = spec.getAllowedTypes();
-            List<TypeMirror> types = spec.getAllowedTypes();
-            if (types != null && allowedTypes.size() > 1) {
-                TypeDef foundDef = null;
-                for (TypeDef def : typeDefs) {
-                    if (allowedTypes.equals(def.getTypes())) {
-                        foundDef = def;
-                        break;
-                    }
-                }
-                if (foundDef == null) {
-                    foundDef = new TypeDef(types, "Types" + defIndex);
-                    typeDefs.add(foundDef);
-                    defIndex++;
-                }
+        public E get() {
+            if (index >= data.size()) {
+                return null;
+            }
+            return data.get(index);
+        }
 
-                foundDef.getParameters().add(spec);
+        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);
             }
         }
 
-        return typeDefs;
-    }
-
-    protected static class TypeDef {
-
-        private final List<TypeMirror> types;
-        private final String name;
-        private final List<ParameterSpec> parameters = new ArrayList<>();
-
-        public TypeDef(List<TypeMirror> types, String name) {
-            this.types = types;
-            this.name = name;
+        public int getIndex() {
+            return index;
         }
 
-        public List<ParameterSpec> getParameters() {
-            return parameters;
-        }
-
-        public List<TypeMirror> getTypes() {
-            return types;
+        @Override
+        public Iterator<E> iterator() {
+            return toList().iterator();
         }
 
-        public String getName() {
-            return name;
-        }
-    }
-
-    public static String createExpectedSignature(String methodName, ParameterSpec returnType, List<? extends ParameterSpec> parameters, List<TypeDef> typeDefs) {
-        StringBuilder b = new StringBuilder();
-
-        b.append("    ");
-        b.append(createTypeSignature(returnType, typeDefs, true));
-
-        b.append(" ");
-        b.append(methodName);
-        b.append("(");
-
-        for (int i = 0; i < parameters.size(); i++) {
-            ParameterSpec specification = parameters.get(i);
-            if (specification.isOptional()) {
-                b.append("[");
+        public List<E> toList() {
+            if (index < data.size()) {
+                return data.subList(index, data.size());
+            } else {
+                return Collections.<E> emptyList();
             }
-            if (specification.getCardinality() == Cardinality.MULTIPLE) {
-                b.append("{");
-            }
-
-            b.append(createTypeSignature(specification, typeDefs, false));
-
-            if (specification.isOptional()) {
-                b.append("]");
-            }
-
-            if (specification.getCardinality() == Cardinality.MULTIPLE) {
-                b.append("}");
-            }
-
-            if (i < parameters.size() - 1) {
-                b.append(", ");
-            }
-
         }
 
-        b.append(")");
-
-        if (!typeDefs.isEmpty()) {
-            b.append("\n\n");
-
-            String lineSep = "";
-            for (TypeDef def : typeDefs) {
-                b.append(lineSep);
-                b.append("    <").append(def.getName()).append(">");
-                b.append(" = {");
-                String separator = "";
-                for (TypeMirror type : def.getTypes()) {
-                    b.append(separator).append(Utils.getSimpleName(type));
-                    separator = ", ";
-                }
-                b.append("}");
-                lineSep = "\n";
-
-            }
-        }
-        return b.toString();
-    }
-
-    private static String createTypeSignature(ParameterSpec spec, List<TypeDef> typeDefs, boolean typeOnly) {
-        StringBuilder builder = new StringBuilder();
-        if (spec.getAllowedTypes().size() > 1) {
-            TypeDef foundTypeDef = null;
-            for (TypeDef typeDef : typeDefs) {
-                if (typeDef.getParameters().contains(spec)) {
-                    foundTypeDef = typeDef;
-                    break;
-                }
-            }
-            if (foundTypeDef != null) {
-                builder.append("<" + foundTypeDef.getName() + ">");
-            }
-        } else if (spec.getAllowedTypes().size() == 1) {
-            builder.append(Utils.getSimpleName(spec.getAllowedTypes().get(0)));
-        } else {
-            builder.append("void");
-        }
-        if (!typeOnly) {
-            builder.append(" ");
-            builder.append(spec.getName());
-        }
-        return builder.toString();
     }
 
 }