diff graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java @ 8242:ac4e8c16ffdf

Added new codegen api classes NodeId, NodeClass to codegen along with some refactorings.
author Christian Humer <christian.humer@gmail.com>
date Mon, 04 Mar 2013 15:14:11 +0100
parents 33e08aca06ff
children d81ff782fa1a
line wrap: on
line diff
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Mon Mar 04 15:13:25 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Mon Mar 04 15:14:11 2013 +0100
@@ -112,10 +112,13 @@
 
     private NodeData parseNode(TypeElement type) {
         if (Utils.findAnnotationMirror(processingEnv, type, GeneratedBy.class) != null) {
-            // generated nodes get called again.
+            // generated nodes should not get called again.
             return null;
         }
-        if (!Utils.isAssignable(type.asType(), context.getTruffleTypes().getNode())) {
+
+        AnnotationMirror methodNodes = Utils.findAnnotationMirror(processingEnv, type, NodeClass.class);
+
+        if (methodNodes == null && !Utils.isAssignable(type.asType(), context.getTruffleTypes().getNode())) {
             return null; // not a node
         }
 
@@ -123,13 +126,149 @@
             return null; // not visible
         }
 
+        final NodeData nodeData = parseNodeData(type);
+        if (nodeData == null) {
+            // TODO error message for instanceBaseClass?
+            return null;
+        }
+
+        List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(type));
+        nodeData.setExtensionElements(getExtensionParser().parseAll(type, elements));
+        if (nodeData.getExtensionElements() != null) {
+            elements.addAll(nodeData.getExtensionElements());
+        }
+
+        if (!parseMethods(nodeData, elements)) {
+            return null;
+        }
+        // TODO split
+
+        if (!finalizeSpecializations(nodeData)) {
+            return null;
+        }
+
+        if (!verifyNode(nodeData)) {
+            return null;
+        }
+
+        return nodeData;
+    }
+
+    private boolean parseMethods(final NodeData node, List<Element> elements) {
+        node.setGuards(new GuardParser(context, node, node.getTypeSystem()).parse(elements));
+        node.setShortCircuits(new ShortCircuitParser(context, node).parse(elements));
+        node.setSpecializationListeners(new SpecializationListenerParser(context, node).parse(elements));
+        List<SpecializationData> generics = new GenericParser(context, node).parse(elements);
+        List<SpecializationData> specializations = new SpecializationMethodParser(context, node).parse(elements);
+
+        if (generics == null || specializations == null || node.getGuards() == null || node.getShortCircuits() == null || node.getSpecializationListeners() == null) {
+            return false;
+        }
+
+        List<SpecializationData> allSpecializations = new ArrayList<>();
+        allSpecializations.addAll(generics);
+        allSpecializations.addAll(specializations);
+
+        node.setSpecializations(allSpecializations);
+
+        return true;
+    }
+
+    private boolean finalizeSpecializations(final NodeData node) {
+        List<SpecializationData> specializations = new ArrayList<>(node.getSpecializations());
+
+        List<SpecializationData> generics = new ArrayList<>();
+        for (SpecializationData spec : specializations) {
+            if (spec.isGeneric()) {
+                generics.add(spec);
+            }
+        }
+
+        SpecializationData genericSpecialization = null;
+        if (generics.size() > 1) {
+            for (SpecializationData generic : generics) {
+                log.error(generic.getMethod(), "Only one method with @%s is allowed per operation.", Generic.class.getSimpleName());
+            }
+            return false;
+        } else if (generics.size() == 1) {
+            genericSpecialization = generics.get(0);
+        }
+
+        if (specializations.size() > 1 && genericSpecialization == null) {
+            log.error(node.getTemplateType(), "Need a @%s method.", Generic.class.getSimpleName());
+            return false;
+        }
+
+        if (genericSpecialization != null) {
+            CodeExecutableElement uninitializedMethod = new CodeExecutableElement(Utils.modifiers(Modifier.PUBLIC), context.getType(void.class), "doUninitialized");
+            TemplateMethod uninializedMethod = new TemplateMethod(genericSpecialization.getId(), node, genericSpecialization.getSpecification(), uninitializedMethod,
+                            genericSpecialization.getMarkerAnnotation(), genericSpecialization.getReturnType(), genericSpecialization.getParameters());
+            specializations.add(new SpecializationData(uninializedMethod, false, true));
+        }
+
+        Collections.sort(specializations, new Comparator<SpecializationData>() {
+
+            @Override
+            public int compare(SpecializationData o1, SpecializationData o2) {
+                return compareSpecialization(node.getTypeSystem(), o1, o2);
+            }
+        });
+
+        node.setSpecializations(specializations);
+
+        return true;
+    }
+
+    private boolean verifyNode(NodeData nodeData) {
+        // verify specialization parameter length
+        if (!verifySpecializationParameters(nodeData)) {
+            return false;
+        }
+
+        // verify order is not ambiguous
+        if (!verifySpecializationOrder(nodeData)) {
+            return false;
+        }
+
+        if (!verifyMissingAbstractMethods(nodeData)) {
+            return false;
+        }
+
+        if (!assignShortCircuitsToSpecializations(nodeData)) {
+            return false;
+        }
+
+        if (!verifyConstructors(nodeData)) {
+            return false;
+        }
+
+// if (!verifyNamingConvention(specializations, "do")) {
+// return null;
+// }
+//
+// if (!verifyNamesUnique(specializations)) {
+// return null;
+// }
+
+        if (!verifyNamingConvention(nodeData.getShortCircuits(), "needs")) {
+            return false;
+        }
+
+        if (!verifySpecializationThrows(nodeData)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private NodeData parseNodeData(TypeElement type) {
         List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(type));
         List<TypeElement> typeHierarchy = findSuperClasses(new ArrayList<TypeElement>(), type);
         Collections.reverse(typeHierarchy);
 
         AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class);
         if (typeSystemMirror == null) {
-            log.error(type, "No @%s annotation found in type hierarchy.", TypeSystemReference.class.getSimpleName());
+            log.error(type, "No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), type.getQualifiedName().toString());
             return null;
         }
 
@@ -142,120 +281,24 @@
 
         NodeData nodeData = new NodeData(type, typeSystem);
 
-        nodeData.setExtensionElements(getExtensionParser().parseAll(type, elements));
-        if (nodeData.getExtensionElements() != null) {
-            elements.addAll(nodeData.getExtensionElements());
-        }
-
         List<ExecutableTypeData> executableTypes = filterExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements));
 
-        nodeData.setExecutableTypes(executableTypes.toArray(new ExecutableTypeData[executableTypes.size()]));
+        nodeData.setExecutableTypes(executableTypes);
 
         parsedNodes.put(Utils.getQualifiedName(type), nodeData);
 
-        NodeFieldData[] fields = parseFields(nodeData, elements, typeHierarchy);
+        List<NodeFieldData> fields = parseFields(nodeData, elements, typeHierarchy);
         if (fields == null) {
             return null;
         }
         nodeData.setFields(fields);
-
-        List<SpecializationData> genericSpecializations = new GenericParser(context, nodeData).parse(elements);
-        List<GuardData> guards = new GuardParser(context, nodeData, nodeData.getTypeSystem()).parse(elements);
-        nodeData.setGuards(guards.toArray(new GuardData[guards.size()]));
-
-        SpecializationMethodParser specializationParser = new SpecializationMethodParser(context, nodeData);
-        List<SpecializationData> specializations = specializationParser.parse(elements);
-        List<ShortCircuitData> shortCircuits = new ShortCircuitParser(context, nodeData).parse(elements);
-        List<TemplateMethod> listeners = new SpecializationListenerParser(context, nodeData).parse(elements);
-
-        if (specializations == null || genericSpecializations == null || shortCircuits == null || listeners == null || guards == null) {
-            return null;
-        }
-
-        SpecializationData genericSpecialization = null;
-        if (genericSpecializations.size() > 1) {
-            for (SpecializationData generic : genericSpecializations) {
-                log.error(generic.getMethod(), "Only one method with @%s is allowed per operation.", Generic.class.getSimpleName());
-            }
-            return null;
-        } else if (genericSpecializations.size() == 1) {
-            genericSpecialization = genericSpecializations.get(0);
-        }
-
-        if (specializations.size() > 1 && genericSpecialization == null) {
-            log.error(type, "Need a @%s method.", Generic.class.getSimpleName());
-            return null;
-        }
-
-        Collections.sort(specializations, new Comparator<SpecializationData>() {
-
-            @Override
-            public int compare(SpecializationData o1, SpecializationData o2) {
-                return compareSpecialization(typeSystem, o1, o2);
-            }
-        });
-
-        List<SpecializationData> allSpecializations = new ArrayList<>(specializations);
-        if (genericSpecialization != null) {
-            allSpecializations.add(genericSpecialization);
-            CodeExecutableElement uninitializedMethod = new CodeExecutableElement(Utils.modifiers(Modifier.PUBLIC), context.getType(void.class), "doUninitialized");
-            TemplateMethod uninializedMethod = new TemplateMethod(nodeData, genericSpecialization.getSpecification(), uninitializedMethod, genericSpecialization.getMarkerAnnotation(),
-                            genericSpecialization.getReturnType(), genericSpecialization.getParameters());
-            allSpecializations.add(0, new SpecializationData(uninializedMethod, false, true));
-        }
-
-        for (SpecializationData specialization : allSpecializations) {
-            specialization.setNode(nodeData);
-        }
-
-        // verify specialization parameter length
-        if (!verifySpecializationParameters(specializations)) {
-            return null;
-        }
-
-        // verify order is not ambiguous
-        if (!verifySpecializationOrder(typeSystem, specializations)) {
-            return null;
-        }
-
-        nodeData.setSpecializations(allSpecializations.toArray(new SpecializationData[allSpecializations.size()]));
-        nodeData.setSpecializationListeners(listeners.toArray(new TemplateMethod[listeners.size()]));
-
-        if (!verifyMissingAbstractMethods(nodeData, elements)) {
-            return null;
-        }
-
-        if (!assignShortCircuitsToSpecializations(nodeData, allSpecializations, shortCircuits)) {
-            return null;
-        }
-
-        if (!verifyConstructors(nodeData)) {
-            return null;
-        }
-
-        if (!verifyNamingConvention(specializations, "do")) {
-            return null;
-        }
-
-        if (!verifyNamesUnique(specializations)) {
-            return null;
-        }
-
-        if (!verifyNamingConvention(shortCircuits, "needs")) {
-            return null;
-        }
-
-        if (!verifySpecializationThrows(typeSystem, specializations)) {
-            return null;
-        }
-
         return nodeData;
     }
 
-    private boolean verifySpecializationParameters(List<SpecializationData> specializations) {
+    private boolean verifySpecializationParameters(NodeData nodeData) {
         boolean valid = true;
         int args = -1;
-        for (SpecializationData specializationData : specializations) {
+        for (SpecializationData specializationData : nodeData.getSpecializations()) {
             int specializationArgs = 0;
             for (ActualParameter param : specializationData.getParameters()) {
                 if (!param.getSpecification().isOptional()) {
@@ -269,20 +312,22 @@
             args = specializationArgs;
         }
         if (!valid) {
-            for (SpecializationData specialization : specializations) {
+            for (SpecializationData specialization : nodeData.getSpecializations()) {
                 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) {
+    private boolean verifyMissingAbstractMethods(NodeData nodeData) {
         if (nodeData.needsFactory()) {
             // missing abstract methods only needs to be implemented
             // if we need go generate factory for it.
             return true;
         }
 
+        List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(nodeData.getTemplateType()));
+
         Set<Element> unusedElements = new HashSet<>(elements);
         for (TemplateMethod method : nodeData.getAllTemplateMethods()) {
             unusedElements.remove(method.getMethod());
@@ -376,7 +421,7 @@
         return null;
     }
 
-    private NodeFieldData[] parseFields(NodeData nodeData, List<? extends Element> elements, final List<TypeElement> typeHierarchy) {
+    private List<NodeFieldData> parseFields(NodeData nodeData, List<? extends Element> elements, final List<TypeElement> typeHierarchy) {
         AnnotationMirror executionOrderMirror = findFirstAnnotation(typeHierarchy, ExecuteChildren.class);
         List<String> executionDefinition = null;
         if (executionOrderMirror != null) {
@@ -423,9 +468,8 @@
             return null;
         }
 
-        NodeFieldData[] fieldArray = fields.toArray(new NodeFieldData[fields.size()]);
-        sortByExecutionOrder(fieldArray, executionDefinition == null ? Collections.<String> emptyList() : executionDefinition, typeHierarchy);
-        return fieldArray;
+        sortByExecutionOrder(fields, executionDefinition == null ? Collections.<String> emptyList() : executionDefinition, typeHierarchy);
+        return fields;
     }
 
     private NodeFieldData parseField(NodeData parentNodeData, VariableElement var, Set<String> foundShortCircuits) {
@@ -510,8 +554,8 @@
         }
     }
 
-    private static void sortByExecutionOrder(NodeFieldData[] fields, final List<String> executionOrder, final List<TypeElement> typeHierarchy) {
-        Arrays.sort(fields, new Comparator<NodeFieldData>() {
+    private static void sortByExecutionOrder(List<NodeFieldData> fields, final List<String> executionOrder, final List<TypeElement> typeHierarchy) {
+        Collections.sort(fields, new Comparator<NodeFieldData>() {
 
             @Override
             public int compare(NodeFieldData o1, NodeFieldData o2) {
@@ -533,18 +577,17 @@
         });
     }
 
-    private boolean assignShortCircuitsToSpecializations(NodeData nodeData, List<SpecializationData> specializations, List<ShortCircuitData> shortCircuits) {
-
-        Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(shortCircuits);
+    private boolean assignShortCircuitsToSpecializations(NodeData node) {
+        Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
 
         boolean valid = true;
 
-        for (NodeFieldData field : nodeData.filterFields(null, ExecutionKind.SHORT_CIRCUIT)) {
+        for (NodeFieldData field : node.filterFields(null, ExecutionKind.SHORT_CIRCUIT)) {
             String valueName = field.getName();
             List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
 
             if (availableCircuits == null || availableCircuits.isEmpty()) {
-                log.error(nodeData.getTemplateType(), "@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
+                log.error(node.getTemplateType(), "@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
                 valid = false;
                 continue;
             }
@@ -567,14 +610,14 @@
 
             ShortCircuitData genericCircuit = null;
             for (ShortCircuitData circuit : availableCircuits) {
-                if (isGenericShortCutMethod(nodeData, circuit)) {
+                if (isGenericShortCutMethod(node, circuit)) {
                     genericCircuit = circuit;
                     break;
                 }
             }
 
             if (genericCircuit == null) {
-                log.error(nodeData.getTemplateType(), "No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
+                log.error(node.getTemplateType(), "No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
                 valid = false;
                 continue;
             }
@@ -590,8 +633,8 @@
             return valid;
         }
 
-        NodeFieldData[] fields = nodeData.filterFields(null, ExecutionKind.SHORT_CIRCUIT);
-        for (SpecializationData specialization : specializations) {
+        NodeFieldData[] fields = node.filterFields(null, ExecutionKind.SHORT_CIRCUIT);
+        for (SpecializationData specialization : node.getSpecializations()) {
             ShortCircuitData[] assignedShortCuts = new ShortCircuitData[fields.length];
 
             for (int i = 0; i < fields.length; i++) {
@@ -696,7 +739,10 @@
         return collection;
     }
 
-    private boolean verifySpecializationOrder(TypeSystemData typeSystem, List<SpecializationData> specializations) {
+    private boolean verifySpecializationOrder(NodeData node) {
+        TypeSystemData typeSystem = node.getTypeSystem();
+        List<SpecializationData> specializations = node.getSpecializations();
+
         for (int i = 0; i < specializations.size(); i++) {
             SpecializationData m1 = specializations.get(i);
             for (int j = i + 1; j < specializations.size(); j++) {
@@ -724,13 +770,15 @@
         return true;
     }
 
-    private boolean verifySpecializationThrows(TypeSystemData typeSystem, List<SpecializationData> specializations) {
+    private boolean verifySpecializationThrows(NodeData node) {
+        TypeSystemData typeSystem = node.getTypeSystem();
+
         Map<String, SpecializationData> specializationMap = new HashMap<>();
-        for (SpecializationData spec : specializations) {
+        for (SpecializationData spec : node.getSpecializations()) {
             specializationMap.put(spec.getMethodName(), spec);
         }
         boolean valid = true;
-        for (SpecializationData sourceSpecialization : specializations) {
+        for (SpecializationData sourceSpecialization : node.getSpecializations()) {
             if (sourceSpecialization.getExceptions() != null) {
                 for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) {
                     SpecializationData targetSpecialization = specializationMap.get(throwsData.getTransitionToName());
@@ -772,8 +820,22 @@
     }
 
     private static int compareSpecializationWithoutOrder(TypeSystemData typeSystem, SpecializationData m1, SpecializationData m2) {
-        if (m1.getSpecification() != m2.getSpecification()) {
-            throw new UnsupportedOperationException("Cannot compare two specializations with different specifications.");
+        if (m1 == m2) {
+            return 0;
+        }
+
+        if (m1.isUninitialized() && !m2.isUninitialized()) {
+            return -1;
+        } else if (!m1.isUninitialized() && m2.isUninitialized()) {
+            return 1;
+        } else if (m1.isGeneric() && !m2.isGeneric()) {
+            return 1;
+        } else if (!m1.isGeneric() && m2.isGeneric()) {
+            return -1;
+        }
+
+        if (m1.getTemplate() != m2.getTemplate()) {
+            throw new UnsupportedOperationException("Cannot compare two specializations with different templates.");
         }
 
         int result = compareActualParameter(typeSystem, m1.getReturnType(), m2.getReturnType());