Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java @ 18776:c0fb70634640
Truffle-DSL: support for frame types Frame, MaterializedFrame. Added validation for frame type consistency. Some refactorings along the way.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 05 Jan 2015 01:31:08 +0100 |
parents | a069a87b9a02 |
children | 941761f6b736 |
comparison
equal
deleted
inserted
replaced
18775:a069a87b9a02 | 18776:c0fb70634640 |
---|---|
43 public class NodeParser extends AbstractParser<NodeData> { | 43 public class NodeParser extends AbstractParser<NodeData> { |
44 | 44 |
45 public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Fallback.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class, | 45 public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Fallback.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class, |
46 NodeChildren.class); | 46 NodeChildren.class); |
47 | 47 |
48 private Map<String, NodeData> parsedNodes; | |
49 | |
50 @Override | 48 @Override |
51 protected NodeData parse(Element element, AnnotationMirror mirror) { | 49 protected NodeData parse(Element element, AnnotationMirror mirror) { |
52 NodeData node = null; | 50 NodeData node = parseRootType((TypeElement) element); |
53 try { | 51 if (Log.isDebug() && node != null) { |
54 parsedNodes = new HashMap<>(); | 52 String dump = node.dump(); |
55 node = resolveNode((TypeElement) element); | 53 log.message(Kind.ERROR, null, null, null, dump); |
56 if (Log.DEBUG) { | 54 } |
57 NodeData parsed = parsedNodes.get(ElementUtils.getQualifiedName((TypeElement) element)); | |
58 if (node != null) { | |
59 String dump = parsed.dump(); | |
60 log.message(Kind.ERROR, null, null, null, dump); | |
61 } | |
62 } | |
63 } finally { | |
64 parsedNodes = null; | |
65 } | |
66 | |
67 return node; | 55 return node; |
68 } | 56 } |
69 | 57 |
70 @Override | 58 @Override |
71 protected NodeData filterErrorElements(NodeData model) { | 59 protected NodeData filterErrorElements(NodeData model) { |
94 @Override | 82 @Override |
95 public List<Class<? extends Annotation>> getTypeDelegatedAnnotationTypes() { | 83 public List<Class<? extends Annotation>> getTypeDelegatedAnnotationTypes() { |
96 return ANNOTATIONS; | 84 return ANNOTATIONS; |
97 } | 85 } |
98 | 86 |
99 private NodeData resolveNode(TypeElement rootType) { | 87 private NodeData parseRootType(TypeElement rootType) { |
100 String typeName = ElementUtils.getQualifiedName(rootType); | |
101 if (parsedNodes.containsKey(typeName)) { | |
102 return parsedNodes.get(typeName); | |
103 } | |
104 | |
105 List<NodeData> enclosedNodes = new ArrayList<>(); | 88 List<NodeData> enclosedNodes = new ArrayList<>(); |
106 for (TypeElement enclosedType : ElementFilter.typesIn(rootType.getEnclosedElements())) { | 89 for (TypeElement enclosedType : ElementFilter.typesIn(rootType.getEnclosedElements())) { |
107 NodeData enclosedChild = resolveNode(enclosedType); | 90 NodeData enclosedChild = parseRootType(enclosedType); |
108 if (enclosedChild != null) { | 91 if (enclosedChild != null) { |
109 enclosedNodes.add(enclosedChild); | 92 enclosedNodes.add(enclosedChild); |
110 } | 93 } |
111 } | 94 } |
112 | |
113 NodeData node = parseNode(rootType); | 95 NodeData node = parseNode(rootType); |
114 if (node == null && !enclosedNodes.isEmpty()) { | 96 if (node == null && !enclosedNodes.isEmpty()) { |
115 node = new NodeData(context, rootType); | 97 node = new NodeData(context, rootType); |
116 } | 98 } |
117 | 99 |
118 if (node != null) { | 100 if (node != null) { |
119 for (NodeData enclosedNode : enclosedNodes) { | 101 for (NodeData enclosedNode : enclosedNodes) { |
120 node.addEnclosedNode(enclosedNode); | 102 node.addEnclosedNode(enclosedNode); |
121 } | 103 } |
122 } | 104 } |
123 | |
124 parsedNodes.put(typeName, node); | |
125 return node; | 105 return node; |
126 } | 106 } |
127 | 107 |
128 private NodeData parseNode(TypeElement originalTemplateType) { | 108 private NodeData parseNode(TypeElement originalTemplateType) { |
129 // reloading the type elements is needed for ecj | 109 // reloading the type elements is needed for ecj |
132 if (ElementUtils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) { | 112 if (ElementUtils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) { |
133 // generated nodes should not get called again. | 113 // generated nodes should not get called again. |
134 return null; | 114 return null; |
135 } | 115 } |
136 | 116 |
137 List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType); | |
138 if (!ElementUtils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) { | 117 if (!ElementUtils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) { |
139 return null; | 118 return null; |
140 } | 119 } |
141 List<Element> elements = new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType)); | 120 |
142 | 121 List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType); |
143 NodeData node = parseNodeData(templateType, elements, lookupTypes); | 122 List<Element> members = loadMembers(templateType); |
144 | 123 // ensure the processed element has at least one @Specialization annotation. |
145 parseImportGuards(node, lookupTypes, elements); | 124 if (!containsSpecializations(members)) { |
125 return null; | |
126 } | |
127 | |
128 NodeData node = parseNodeData(templateType, lookupTypes); | |
129 | |
130 node.getAssumptions().addAll(parseAssumptions(lookupTypes)); | |
131 node.getFields().addAll(parseFields(lookupTypes, members)); | |
132 node.getChildren().addAll(parseChildren(lookupTypes, members)); | |
133 node.getChildExecutions().addAll(parseExecutions(node.getChildren(), members)); | |
134 node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node, context.getFrameTypes()).parse(members))); | |
135 | |
136 initializeExecutableTypes(node); | |
137 initializeImportGuards(node, lookupTypes, members); | |
146 | 138 |
147 if (node.hasErrors()) { | 139 if (node.hasErrors()) { |
148 return node; // error sync point | 140 return node; // error sync point |
149 } | 141 } |
150 | 142 |
151 initializeExecutableTypes(elements, node); | |
152 initializeChildren(node); | 143 initializeChildren(node); |
153 | 144 |
154 // ensure the processed element has at least one @Specialization annotation. | 145 if (node.hasErrors()) { |
146 return node; // error sync point | |
147 } | |
148 | |
149 node.getSpecializations().addAll(new SpecializationMethodParser(context, node).parse(members)); | |
150 node.getSpecializations().addAll(new GenericParser(context, node).parse(members)); | |
151 node.getCasts().addAll(new CreateCastParser(context, node).parse(members)); | |
152 node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(members)); | |
153 | |
154 if (node.hasErrors()) { | |
155 return node; // error sync point | |
156 } | |
157 | |
158 verifySpecializationSameLength(node); | |
159 initializeSpecializations(members, node); | |
160 initializeShortCircuits(node); // requires specializations and polymorphic specializations | |
161 | |
162 verifyVisibilities(node); | |
163 verifyMissingAbstractMethods(node, members); | |
164 verifyConstructors(node); | |
165 verifyNamingConvention(node.getShortCircuits(), "needs"); | |
166 verifySpecializationThrows(node); | |
167 return node; | |
168 } | |
169 | |
170 private ArrayList<Element> loadMembers(TypeElement templateType) { | |
171 return new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType)); | |
172 } | |
173 | |
174 private boolean containsSpecializations(List<Element> elements) { | |
155 boolean foundSpecialization = false; | 175 boolean foundSpecialization = false; |
156 for (ExecutableElement method : ElementFilter.methodsIn(elements)) { | 176 for (ExecutableElement method : ElementFilter.methodsIn(elements)) { |
157 if (ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class) != null) { | 177 if (ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class) != null) { |
158 foundSpecialization = true; | 178 foundSpecialization = true; |
159 break; | 179 break; |
160 } | 180 } |
161 } | 181 } |
162 if (!foundSpecialization) { | 182 return foundSpecialization; |
163 return node; | 183 } |
164 } | 184 |
165 | 185 private void initializeImportGuards(NodeData node, List<TypeElement> lookupTypes, List<Element> elements) { |
166 if (node.hasErrors()) { | |
167 return node; // error sync point | |
168 } | |
169 | |
170 node.getSpecializations().addAll(new SpecializationMethodParser(context, node).parse(elements)); | |
171 node.getSpecializations().addAll(new GenericParser(context, node).parse(elements)); | |
172 node.getCasts().addAll(new CreateCastParser(context, node).parse(elements)); | |
173 node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(elements)); | |
174 | |
175 if (node.hasErrors()) { | |
176 return node; // error sync point | |
177 } | |
178 | |
179 verifySpecializationSameLength(node); | |
180 initializeSpecializations(elements, node); | |
181 initializeShortCircuits(node); // requires specializations and polymorphic specializations | |
182 | |
183 verifyVisibilities(node); | |
184 verifyMissingAbstractMethods(node, elements); | |
185 verifyConstructors(node); | |
186 verifyNamingConvention(node.getShortCircuits(), "needs"); | |
187 verifySpecializationThrows(node); | |
188 return node; | |
189 } | |
190 | |
191 private void parseImportGuards(NodeData node, List<TypeElement> lookupTypes, List<Element> elements) { | |
192 for (TypeElement lookupType : lookupTypes) { | 186 for (TypeElement lookupType : lookupTypes) { |
193 AnnotationMirror importAnnotation = ElementUtils.findAnnotationMirror(processingEnv, lookupType, ImportGuards.class); | 187 AnnotationMirror importAnnotation = ElementUtils.findAnnotationMirror(processingEnv, lookupType, ImportGuards.class); |
194 if (importAnnotation == null) { | 188 if (importAnnotation == null) { |
195 continue; | 189 continue; |
196 } | 190 } |
226 } | 220 } |
227 } | 221 } |
228 } | 222 } |
229 } | 223 } |
230 | 224 |
231 private NodeData parseNodeData(TypeElement templateType, List<? extends Element> elements, List<TypeElement> typeHierarchy) { | 225 private NodeData parseNodeData(TypeElement templateType, List<TypeElement> typeHierarchy) { |
232 AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); | 226 AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); |
233 if (typeSystemMirror == null) { | 227 if (typeSystemMirror == null) { |
234 NodeData nodeData = new NodeData(context, templateType); | 228 NodeData nodeData = new NodeData(context, templateType); |
235 nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), ElementUtils.getQualifiedName(templateType)); | 229 nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), ElementUtils.getQualifiedName(templateType)); |
236 return nodeData; | 230 return nodeData; |
242 NodeData nodeData = new NodeData(context, templateType); | 236 NodeData nodeData = new NodeData(context, templateType); |
243 nodeData.addError("The used type system '%s' is invalid. Fix errors in the type system first.", ElementUtils.getQualifiedName(typeSystemType)); | 237 nodeData.addError("The used type system '%s' is invalid. Fix errors in the type system first.", ElementUtils.getQualifiedName(typeSystemType)); |
244 return nodeData; | 238 return nodeData; |
245 } | 239 } |
246 | 240 |
241 AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class); | |
242 String shortName = null; | |
243 if (nodeInfoMirror != null) { | |
244 shortName = ElementUtils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"); | |
245 } | |
246 boolean useNodeFactory = findFirstAnnotation(typeHierarchy, GenerateNodeFactory.class) != null; | |
247 return new NodeData(context, templateType, shortName, typeSystem, useNodeFactory); | |
248 | |
249 } | |
250 | |
251 private List<String> parseAssumptions(List<TypeElement> typeHierarchy) { | |
247 List<String> assumptionsList = new ArrayList<>(); | 252 List<String> assumptionsList = new ArrayList<>(); |
248 for (int i = typeHierarchy.size() - 1; i >= 0; i--) { | 253 for (int i = typeHierarchy.size() - 1; i >= 0; i--) { |
249 TypeElement type = typeHierarchy.get(i); | 254 TypeElement type = typeHierarchy.get(i); |
250 AnnotationMirror assumptions = ElementUtils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class); | 255 AnnotationMirror assumptions = ElementUtils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class); |
251 if (assumptions != null) { | 256 if (assumptions != null) { |
256 } | 261 } |
257 assumptionsList.add(string); | 262 assumptionsList.add(string); |
258 } | 263 } |
259 } | 264 } |
260 } | 265 } |
261 AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class); | 266 return assumptionsList; |
262 String shortName = null; | |
263 if (nodeInfoMirror != null) { | |
264 shortName = ElementUtils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"); | |
265 } | |
266 | |
267 List<NodeFieldData> fields = parseFields(typeHierarchy, elements); | |
268 List<NodeChildData> children = parseChildren(typeHierarchy, elements); | |
269 List<NodeExecutionData> executions = parseExecutions(children, elements); | |
270 boolean useNodeFactory = findFirstAnnotation(typeHierarchy, GenerateNodeFactory.class) != null; | |
271 | |
272 NodeData nodeData = new NodeData(context, templateType, shortName, typeSystem, children, executions, fields, assumptionsList, useNodeFactory); | |
273 | |
274 parsedNodes.put(ElementUtils.getQualifiedName(templateType), nodeData); | |
275 | |
276 return nodeData; | |
277 } | 267 } |
278 | 268 |
279 private List<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) { | 269 private List<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) { |
280 Set<String> names = new HashSet<>(); | 270 Set<String> names = new HashSet<>(); |
281 | 271 |
467 } else { | 457 } else { |
468 maxSignatureSize = children.size(); | 458 maxSignatureSize = children.size(); |
469 } | 459 } |
470 } | 460 } |
471 | 461 |
472 // pre-parse specializations | 462 List<TypeMirror> frameTypes = context.getFrameTypes(); |
463 // pre-parse specializations to find signature size | |
473 for (ExecutableElement method : methods) { | 464 for (ExecutableElement method : methods) { |
474 AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class); | 465 AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class); |
475 if (mirror == null) { | 466 if (mirror == null) { |
476 continue; | 467 continue; |
477 } | 468 } |
478 | 469 |
479 int currentArgumentCount = 0; | 470 int currentArgumentIndex = 0; |
480 boolean skipShortCircuit = false; | 471 boolean skipShortCircuit = false; |
481 for (VariableElement var : method.getParameters()) { | 472 outer: for (VariableElement var : method.getParameters()) { |
482 TypeMirror type = var.asType(); | 473 TypeMirror type = var.asType(); |
483 if (currentArgumentCount == 0) { | 474 if (currentArgumentIndex == 0) { |
484 // skip optionals | 475 // skip optionals |
485 if (ElementUtils.typeEquals(type, context.getTruffleTypes().getFrame())) { | 476 for (TypeMirror frameType : frameTypes) { |
486 continue; | 477 if (ElementUtils.typeEquals(type, frameType)) { |
478 continue outer; | |
479 } | |
487 } | 480 } |
488 // TODO skip optional fields? | 481 } |
489 } | 482 int childIndex = currentArgumentIndex < children.size() ? currentArgumentIndex : children.size() - 1; |
490 int childIndex = currentArgumentCount < children.size() ? currentArgumentCount : children.size() - 1; | |
491 if (childIndex == -1) { | 483 if (childIndex == -1) { |
492 continue; | 484 continue; |
493 } | 485 } |
494 if (!skipShortCircuit) { | 486 if (!skipShortCircuit) { |
495 NodeChildData child = children.get(childIndex); | 487 NodeChildData child = children.get(childIndex); |
496 if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentCount - childIndex))) { | 488 if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentIndex - childIndex))) { |
497 skipShortCircuit = true; | 489 skipShortCircuit = true; |
498 continue; | 490 continue; |
499 } | 491 } |
500 } else { | 492 } else { |
501 skipShortCircuit = false; | 493 skipShortCircuit = false; |
502 } | 494 } |
503 | 495 |
504 currentArgumentCount++; | 496 currentArgumentIndex++; |
505 } | 497 } |
506 maxSignatureSize = Math.max(maxSignatureSize, currentArgumentCount); | 498 maxSignatureSize = Math.max(maxSignatureSize, currentArgumentIndex); |
507 } | 499 } |
508 | 500 |
509 List<NodeExecutionData> executions = new ArrayList<>(); | 501 List<NodeExecutionData> executions = new ArrayList<>(); |
510 for (int i = 0; i < maxSignatureSize; i++) { | 502 for (int i = 0; i < maxSignatureSize; i++) { |
511 int childIndex = i; | 503 int childIndex = i; |
524 executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit)); | 516 executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit)); |
525 } | 517 } |
526 return executions; | 518 return executions; |
527 } | 519 } |
528 | 520 |
529 private void initializeExecutableTypes(List<Element> elements, NodeData node) { | 521 private void initializeExecutableTypes(NodeData node) { |
530 node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node).parse(elements))); | 522 List<ExecutableTypeData> genericExecutes = node.findGenericExecutableTypes(context, 0); |
531 List<ExecutableTypeData> genericExecutes = node.getThisExecution().getChild().findGenericExecutableTypes(context); | 523 List<ExecutableTypeData> allExecutes = node.getExecutableTypes(); |
532 | 524 |
533 List<ExecutableTypeData> overridableGenericExecutes = new ArrayList<>(); | 525 Set<String> inconsistentFrameTypes = new HashSet<>(); |
526 TypeMirror frameType = null; | |
527 Set<Integer> evaluatedCounts = new HashSet<>(); | |
528 for (ExecutableTypeData execute : allExecutes) { | |
529 evaluatedCounts.add(execute.getEvaluatedCount()); | |
530 | |
531 Parameter frame = execute.getFrame(); | |
532 TypeMirror resolvedFrameType; | |
533 if (frame == null) { | |
534 resolvedFrameType = node.getTypeSystem().getVoidType().getPrimitiveType(); | |
535 } else { | |
536 resolvedFrameType = frame.getType(); | |
537 } | |
538 | |
539 if (frameType == null) { | |
540 frameType = resolvedFrameType; | |
541 } else { | |
542 if (!ElementUtils.typeEquals(frameType, resolvedFrameType)) { | |
543 // found inconsistent frame types | |
544 inconsistentFrameTypes.add(ElementUtils.getSimpleName(frameType)); | |
545 inconsistentFrameTypes.add(ElementUtils.getSimpleName(resolvedFrameType)); | |
546 } | |
547 } | |
548 } | |
549 if (!inconsistentFrameTypes.isEmpty()) { | |
550 // ensure they are sorted somehow | |
551 List<String> inconsistentFrameTypesList = new ArrayList<>(inconsistentFrameTypes); | |
552 Collections.sort(inconsistentFrameTypesList); | |
553 node.addError("Invalid inconsistent frame types %s found for the declared execute methods. The frame type must be identical for all execute methods.", inconsistentFrameTypesList); | |
554 } | |
555 node.setFrameType(frameType); | |
556 | |
557 int nonFinalCount = 0; | |
558 int voidCount = 0; | |
534 for (ExecutableTypeData executableTypeData : genericExecutes) { | 559 for (ExecutableTypeData executableTypeData : genericExecutes) { |
535 if (!executableTypeData.getMethod().getModifiers().contains(Modifier.FINAL)) { | 560 if (!executableTypeData.getMethod().getModifiers().contains(Modifier.FINAL)) { |
536 overridableGenericExecutes.add(executableTypeData); | 561 nonFinalCount++; |
537 } | 562 } |
538 } | 563 if (ElementUtils.isVoid(executableTypeData.getReturnType().getType())) { |
539 | 564 voidCount++; |
540 if (overridableGenericExecutes.isEmpty()) { | 565 } |
566 } | |
567 | |
568 // no generic executes | |
569 if (nonFinalCount == 0 && voidCount == 0) { | |
541 node.addError("No accessible and overridable generic execute method found. Generic execute methods usually have the " | 570 node.addError("No accessible and overridable generic execute method found. Generic execute methods usually have the " |
542 + "signature 'public abstract {Type} executeGeneric(VirtualFrame)' and must not throw any checked exceptions."); | 571 + "signature 'public abstract {Type} execute(VirtualFrame)' and must not throw any checked exceptions."); |
543 } | 572 } |
544 | 573 |
545 if (overridableGenericExecutes.size() > 1) { | 574 // multiple generic execute |
575 if (voidCount > 1 || (nonFinalCount - voidCount) > 1) { | |
546 List<String> methodSignatures = new ArrayList<>(); | 576 List<String> methodSignatures = new ArrayList<>(); |
547 for (ExecutableTypeData type : overridableGenericExecutes) { | 577 for (ExecutableTypeData type : genericExecutes) { |
548 methodSignatures.add(type.createReferenceName()); | 578 methodSignatures.add(type.createReferenceName()); |
549 } | 579 } |
550 node.addWarning("Multiple accessible and overridable generic execute methods found %s. Remove all but one or mark all but one as final.", methodSignatures); | 580 node.addWarning("Multiple accessible and overridable generic execute methods found %s. Remove all but one or mark all but one as final.", methodSignatures); |
551 } | 581 } |
552 } | 582 } |
569 } | 599 } |
570 return groupedTypes; | 600 return groupedTypes; |
571 } | 601 } |
572 | 602 |
573 private void initializeChildren(NodeData node) { | 603 private void initializeChildren(NodeData node) { |
574 for (NodeChildData nodeChild : node.getChildren()) { | 604 for (NodeChildData child : node.getChildren()) { |
575 NodeData fieldNodeData = resolveNode(ElementUtils.fromTypeMirror(nodeChild.getNodeType())); | 605 TypeMirror nodeType = child.getNodeType(); |
576 nodeChild.setNode(fieldNodeData); | 606 NodeData fieldNodeData = parseChildNodeData(node, ElementUtils.fromTypeMirror(nodeType)); |
577 if (fieldNodeData == null) { | 607 |
578 nodeChild.addError("Node type '%s' is invalid or not a valid Node.", ElementUtils.getQualifiedName(nodeChild.getNodeType())); | 608 child.setNode(fieldNodeData); |
609 if (fieldNodeData == null || fieldNodeData.hasErrors()) { | |
610 child.addError("Node type '%s' is invalid or not a subclass of Node.", ElementUtils.getQualifiedName(nodeType)); | |
579 } else if (!ElementUtils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) { | 611 } else if (!ElementUtils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) { |
580 nodeChild.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(), | 612 child.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(), |
581 NodeChild.class.getSimpleName(), ElementUtils.getSimpleName(node.getTypeSystem().getTemplateType()), | 613 NodeChild.class.getSimpleName(), ElementUtils.getSimpleName(node.getTypeSystem().getTemplateType()), |
582 ElementUtils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType())); | 614 ElementUtils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType())); |
583 } else if (nodeChild.findAnyGenericExecutableType(context) == null) { | 615 } else { |
584 nodeChild.addError("No generic execute method found for child type %s. Generic execute methods usually have the signature 'Object executeGeneric(VirtualFrame)'.", | 616 List<ExecutableTypeData> types = child.findGenericExecutableTypes(context); |
585 ElementUtils.getQualifiedName(nodeChild.getNodeType())); | |
586 } | |
587 if (fieldNodeData != null) { | |
588 List<ExecutableTypeData> types = nodeChild.findGenericExecutableTypes(context); | |
589 if (types.isEmpty()) { | 617 if (types.isEmpty()) { |
590 AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(nodeChild.getMessageAnnotation(), "executeWith"); | 618 AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith"); |
591 nodeChild.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", nodeChild.getExecuteWith().size(), | 619 child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s and frame types %s.", child.getExecuteWith().size(), |
592 ElementUtils.getSimpleName(nodeChild.getNodeType())); | 620 ElementUtils.getSimpleName(nodeType), ElementUtils.getUniqueIdentifiers(createAllowedChildFrameTypes(node))); |
593 } | 621 } |
594 } | 622 } |
595 } | 623 } |
624 } | |
625 | |
626 private NodeData parseChildNodeData(NodeData parentNode, TypeElement originalTemplateType) { | |
627 TypeElement templateType = ElementUtils.fromTypeMirror(context.reloadTypeElement(originalTemplateType)); | |
628 | |
629 if (ElementUtils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) { | |
630 // generated nodes should not get called again. | |
631 return null; | |
632 } | |
633 | |
634 if (!ElementUtils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) { | |
635 return null; | |
636 } | |
637 | |
638 List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType); | |
639 | |
640 // Declaration order is not required for child nodes. | |
641 List<? extends Element> members = processingEnv.getElementUtils().getAllMembers(templateType); | |
642 NodeData node = parseNodeData(templateType, lookupTypes); | |
643 | |
644 node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node, createAllowedChildFrameTypes(parentNode)).parse(members))); | |
645 node.setFrameType(parentNode.getFrameType()); | |
646 return node; | |
647 } | |
648 | |
649 private List<TypeMirror> createAllowedChildFrameTypes(NodeData parentNode) { | |
650 List<TypeMirror> allowedFrameTypes = new ArrayList<>(); | |
651 for (TypeMirror frameType : context.getFrameTypes()) { | |
652 if (ElementUtils.isAssignable(parentNode.getFrameType(), frameType)) { | |
653 allowedFrameTypes.add(frameType); | |
654 } | |
655 } | |
656 return allowedFrameTypes; | |
596 } | 657 } |
597 | 658 |
598 private void initializeSpecializations(List<? extends Element> elements, final NodeData node) { | 659 private void initializeSpecializations(List<? extends Element> elements, final NodeData node) { |
599 if (node.getSpecializations().isEmpty()) { | 660 if (node.getSpecializations().isEmpty()) { |
600 return; | 661 return; |