diff graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java @ 11187:7a8835ec5e7d

Truffle-DSL: Added new @NodeField and @NodeFields annotation. Which can be used to avoid the cumbersome definition of copy constructors.
author Christian Humer <christian.humer@gmail.com>
date Tue, 30 Jul 2013 17:42:50 +0200
parents 0f5ff66a949d
children 6879565ee10b
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Tue Jul 30 16:12:26 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Tue Jul 30 17:42:50 2013 +0200
@@ -277,10 +277,10 @@
         node.setPolymorphicSpecializations(specializations);
     }
 
-    private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List<? extends Element> elements, List<TypeElement> lookupTypes) {
+    private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List<? extends Element> elements, List<TypeElement> typeHierarchy) {
         NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString());
 
-        AnnotationMirror typeSystemMirror = findFirstAnnotation(lookupTypes, TypeSystemReference.class);
+        AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class);
         if (typeSystemMirror == null) {
             nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(nodeType));
             return nodeData;
@@ -293,7 +293,7 @@
             return nodeData;
         }
 
-        AnnotationMirror polymorphicMirror = findFirstAnnotation(lookupTypes, PolymorphicLimit.class);
+        AnnotationMirror polymorphicMirror = findFirstAnnotation(typeHierarchy, PolymorphicLimit.class);
         if (polymorphicMirror != null) {
             AnnotationValue limitValue = Utils.getAnnotationValue(polymorphicMirror, "value");
             int polymorphicLimit = Utils.getAnnotationValue(Integer.class, polymorphicMirror, "value");
@@ -304,8 +304,8 @@
         }
 
         List<String> assumptionsList = new ArrayList<>();
-        for (int i = lookupTypes.size() - 1; i >= 0; i--) {
-            TypeElement type = lookupTypes.get(i);
+        for (int i = typeHierarchy.size() - 1; i >= 0; i--) {
+            TypeElement type = typeHierarchy.get(i);
             AnnotationMirror assumptions = Utils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class);
             if (assumptions != null) {
                 List<String> assumptionStrings = Utils.getAnnotationValueList(String.class, assumptions, "value");
@@ -317,35 +317,66 @@
                 }
             }
         }
-        AnnotationMirror nodeInfoMirror = findFirstAnnotation(lookupTypes, NodeInfo.class);
+        AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class);
         if (nodeInfoMirror != null) {
             nodeData.setShortName(Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"));
         }
 
         nodeData.setAssumptions(new ArrayList<>(assumptionsList));
         nodeData.setNodeType(nodeType);
-        AnnotationMirror nodeContainer = findFirstAnnotation(lookupTypes, NodeContainer.class);
+        AnnotationMirror nodeContainer = findFirstAnnotation(typeHierarchy, NodeContainer.class);
         nodeData.setNodeContainer(nodeContainer != null);
         nodeData.setTypeSystem(typeSystem);
-        nodeData.setFields(parseFields(elements));
+        nodeData.setFields(parseFields(typeHierarchy, elements));
         parsedNodes.put(Utils.getQualifiedName(templateType), nodeData);
         // parseChildren invokes cyclic parsing.
-        nodeData.setChildren(parseChildren(elements, lookupTypes));
+        nodeData.setChildren(parseChildren(elements, typeHierarchy));
         nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
 
         return nodeData;
     }
 
-    private static List<NodeFieldData> parseFields(List<? extends Element> elements) {
+    private List<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) {
+        Set<String> names = new HashSet<>();
+
         List<NodeFieldData> fields = new ArrayList<>();
         for (VariableElement field : ElementFilter.fieldsIn(elements)) {
             if (field.getModifiers().contains(Modifier.STATIC)) {
                 continue;
             }
             if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) {
-                fields.add(new NodeFieldData(field));
+                String name = field.getSimpleName().toString();
+                fields.add(new NodeFieldData(field, null, field.asType(), name, false));
+                names.add(name);
             }
         }
+
+        List<TypeElement> reversedTypeHierarchy = new ArrayList<>(typeHierarchy);
+        Collections.reverse(reversedTypeHierarchy);
+        for (TypeElement typeElement : reversedTypeHierarchy) {
+            AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, typeElement, NodeFields.class);
+            List<AnnotationMirror> children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", typeElement, NodeField.class);
+
+            for (AnnotationMirror mirror : children) {
+                String name = Utils.firstLetterLowerCase(Utils.getAnnotationValue(String.class, mirror, "name"));
+                TypeMirror type = Utils.getAnnotationValue(TypeMirror.class, mirror, "type");
+
+                NodeFieldData field = new NodeFieldData(typeElement, mirror, type, name, true);
+                if (name.isEmpty()) {
+                    field.addError(Utils.getAnnotationValue(mirror, "name"), "Field name cannot be empty.");
+                } else if (names.contains(name)) {
+                    field.addError(Utils.getAnnotationValue(mirror, "name"), "Duplicate field name '%s'.", name);
+                }
+                names.add(name);
+
+                fields.add(field);
+            }
+        }
+
+        for (NodeFieldData nodeFieldData : fields) {
+            nodeFieldData.setGetter(findGetter(elements, nodeFieldData.getName(), nodeFieldData.getType()));
+        }
+
         return fields;
     }
 
@@ -975,6 +1006,12 @@
             unusedElements.removeAll(nodeData.getExtensionElements());
         }
 
+        for (NodeFieldData field : nodeData.getFields()) {
+            if (field.getGetter() != null) {
+                unusedElements.remove(field.getGetter());
+            }
+        }
+
         for (NodeChildData child : nodeData.getChildren()) {
             if (child.getAccessElement() != null) {
                 unusedElements.remove(child.getAccessElement());
@@ -1142,7 +1179,7 @@
         }
     }
 
-    private Element findGetter(List<? extends Element> elements, String variableName, TypeMirror type) {
+    private ExecutableElement findGetter(List<? extends Element> elements, String variableName, TypeMirror type) {
         if (type == null) {
             return null;
         }