comparison graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java @ 10591:3cc5fb59916e

Truffle-DSL: Renamed @NodeClass to @NodeContainer. splitByMethodName is not an option anymore and is always enabled if a @NodeContainer is used.
author Christian Humer <christian.humer@gmail.com>
date Fri, 28 Jun 2013 12:19:51 +0200
parents 746fa60be266
children f43eb2f1bbbc
comparison
equal deleted inserted replaced
10590:6eb8d63cea34 10591:3cc5fb59916e
29 import javax.lang.model.type.*; 29 import javax.lang.model.type.*;
30 import javax.lang.model.util.*; 30 import javax.lang.model.util.*;
31 import javax.tools.Diagnostic.Kind; 31 import javax.tools.Diagnostic.Kind;
32 32
33 import com.oracle.truffle.api.codegen.*; 33 import com.oracle.truffle.api.codegen.*;
34 import com.oracle.truffle.api.codegen.NodeClass.InheritNode;
35 import com.oracle.truffle.api.nodes.*; 34 import com.oracle.truffle.api.nodes.*;
36 import com.oracle.truffle.codegen.processor.*; 35 import com.oracle.truffle.codegen.processor.*;
37 import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; 36 import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality;
38 import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; 37 import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind;
39 import com.oracle.truffle.codegen.processor.template.*; 38 import com.oracle.truffle.codegen.processor.template.*;
40 import com.oracle.truffle.codegen.processor.typesystem.*; 39 import com.oracle.truffle.codegen.processor.typesystem.*;
41 40
42 public class NodeParser extends TemplateParser<NodeData> { 41 public class NodeParser extends TemplateParser<NodeData> {
43 42
44 public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class, 43 public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class,
45 NodeClass.class, NodeChild.class, NodeChildren.class, NodeId.class); 44 NodeContainer.class, NodeChild.class, NodeChildren.class, NodeId.class);
46 45
47 private Map<String, NodeData> parsedNodes; 46 private Map<String, NodeData> parsedNodes;
48 47
49 public NodeParser(ProcessorContext c) { 48 public NodeParser(ProcessorContext c) {
50 super(c); 49 super(c);
88 @Override 87 @Override
89 public boolean isDelegateToRootDeclaredType() { 88 public boolean isDelegateToRootDeclaredType() {
90 return true; 89 return true;
91 } 90 }
92 91
92 @Override
93 public Class<? extends Annotation> getAnnotationType() {
94 return null;
95 }
96
97 @Override
98 public List<Class<? extends Annotation>> getTypeDelegatedAnnotationTypes() {
99 return ANNOTATIONS;
100 }
101
93 private NodeData resolveNode(TypeElement rootType) { 102 private NodeData resolveNode(TypeElement rootType) {
94 String typeName = Utils.getQualifiedName(rootType); 103 String typeName = Utils.getQualifiedName(rootType);
95 if (parsedNodes.containsKey(typeName)) { 104 if (parsedNodes.containsKey(typeName)) {
96 return parsedNodes.get(typeName); 105 return parsedNodes.get(typeName);
97 } 106 }
131 } 140 }
132 141
133 List<TypeElement> lookupTypes = findSuperClasses(new ArrayList<TypeElement>(), templateType); 142 List<TypeElement> lookupTypes = findSuperClasses(new ArrayList<TypeElement>(), templateType);
134 Collections.reverse(lookupTypes); 143 Collections.reverse(lookupTypes);
135 144
136 AnnotationMirror nodeClass = findFirstAnnotation(lookupTypes, NodeClass.class); 145 AnnotationMirror nodeClass = findFirstAnnotation(lookupTypes, NodeContainer.class);
137 TypeMirror nodeType = null; 146 TypeMirror nodeType = null;
138 if (Utils.isAssignable(context, templateType.asType(), context.getTruffleTypes().getNode())) { 147 if (Utils.isAssignable(context, templateType.asType(), context.getTruffleTypes().getNode())) {
139 nodeType = templateType.asType(); 148 nodeType = templateType.asType();
140 } 149 }
141 if (nodeClass != null) { 150 if (nodeClass != null) {
150 // FIXME nodeType not specified error 159 // FIXME nodeType not specified error
151 return null; 160 return null;
152 } 161 }
153 } 162 }
154 163
155 Set<Element> elementSet = new HashSet<>(context.getEnvironment().getElementUtils().getAllMembers(templateType)); 164 Elements elementUtil = context.getEnvironment().getElementUtils();
165 Set<Element> elementSet = new HashSet<>(elementUtil.getAllMembers(templateType));
156 if (!Utils.typeEquals(templateType.asType(), nodeType)) { 166 if (!Utils.typeEquals(templateType.asType(), nodeType)) {
157 elementSet.addAll(context.getEnvironment().getElementUtils().getAllMembers(Utils.fromTypeMirror(nodeType))); 167 elementSet.addAll(elementUtil.getAllMembers(Utils.fromTypeMirror(nodeType)));
158 168
159 List<TypeElement> nodeLookupTypes = findSuperClasses(new ArrayList<TypeElement>(), Utils.fromTypeMirror(nodeType)); 169 List<TypeElement> nodeLookupTypes = findSuperClasses(new ArrayList<TypeElement>(), Utils.fromTypeMirror(nodeType));
160 Collections.reverse(nodeLookupTypes); 170 Collections.reverse(nodeLookupTypes);
161 lookupTypes.addAll(nodeLookupTypes); 171 lookupTypes.addAll(nodeLookupTypes);
162 172
184 return node; 194 return node;
185 } 195 }
186 196
187 List<NodeData> nodes; 197 List<NodeData> nodes;
188 198
189 if (node.isSplitByMethodName()) { 199 if (node.isNodeContainer()) {
190 nodes = splitNodeData(node); 200 nodes = splitNodeData(node);
191 } else { 201 } else {
192 nodes = new ArrayList<>(); 202 nodes = new ArrayList<>();
193 nodes.add(node); 203 nodes.add(node);
194 } 204 }
196 for (NodeData splittedNode : nodes) { 206 for (NodeData splittedNode : nodes) {
197 finalizeSpecializations(elements, splittedNode); 207 finalizeSpecializations(elements, splittedNode);
198 verifyNode(splittedNode, elements); 208 verifyNode(splittedNode, elements);
199 } 209 }
200 210
201 if (node.isSplitByMethodName()) { 211 if (node.isNodeContainer()) {
202 node.setDeclaredNodes(nodes); 212 node.setDeclaredNodes(nodes);
203 node.setSpecializationListeners(new ArrayList<SpecializationListenerData>()); 213 node.setSpecializationListeners(new ArrayList<SpecializationListenerData>());
204 node.setSpecializations(new ArrayList<SpecializationData>()); 214 node.setSpecializations(new ArrayList<SpecializationData>());
205 return node; 215 return node;
206 } else { 216 } else {
207 return node; 217 return node;
208 } 218 }
209 } 219 }
210 220
211 private static List<NodeData> splitNodeData(NodeData node) { 221 private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List<? extends Element> elements, List<TypeElement> lookupTypes) {
212 SortedMap<String, List<SpecializationData>> groupedSpecializations = groupByNodeId(node.getSpecializations()); 222 NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString());
213 SortedMap<String, List<SpecializationListenerData>> groupedListeners = groupByNodeId(node.getSpecializationListeners()); 223
214 SortedMap<String, List<CreateCastData>> groupedCasts = groupByNodeId(node.getCasts()); 224 AnnotationMirror typeSystemMirror = findFirstAnnotation(lookupTypes, TypeSystemReference.class);
215 225 if (typeSystemMirror == null) {
216 Set<String> ids = new TreeSet<>(); 226 nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(nodeType));
217 ids.addAll(groupedSpecializations.keySet()); 227 return nodeData;
218 ids.addAll(groupedListeners.keySet()); 228 }
219 229
220 List<NodeData> splitted = new ArrayList<>(); 230 TypeMirror typeSytemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value");
221 for (String id : ids) { 231 final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true);
222 List<SpecializationData> specializations = groupedSpecializations.get(id); 232 if (typeSystem == null) {
223 List<SpecializationListenerData> listeners = groupedListeners.get(id); 233 nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSytemType));
224 List<CreateCastData> casts = groupedCasts.get(id); 234 return nodeData;
225 235 }
226 if (specializations == null) { 236
227 specializations = new ArrayList<>(); 237 List<String> assumptionsList = new ArrayList<>();
228 } 238
229 239 for (int i = lookupTypes.size() - 1; i >= 0; i--) {
230 if (listeners == null) { 240 TypeElement type = lookupTypes.get(i);
231 listeners = new ArrayList<>(); 241 AnnotationMirror assumptions = Utils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class);
232 } 242 if (assumptions != null) {
233 243 List<String> assumptionStrings = Utils.getAnnotationValueList(String.class, assumptions, "value");
234 String nodeId = node.getNodeId(); 244 for (String string : assumptionStrings) {
235 if (nodeId.endsWith("Node") && !nodeId.equals("Node")) { 245 if (assumptionsList.contains(string)) {
236 nodeId = nodeId.substring(0, nodeId.length() - 4); 246 assumptionsList.remove(string);
237 } 247 }
238 String newNodeId = nodeId + Utils.firstLetterUpperCase(id); 248 assumptionsList.add(string);
239 NodeData copy = new NodeData(node, id, newNodeId); 249 }
240 250 }
241 copy.setSpecializations(specializations); 251 }
242 copy.setSpecializationListeners(listeners); 252 AnnotationMirror nodeInfoMirror = findFirstAnnotation(lookupTypes, NodeInfo.class);
243 copy.setCasts(casts); 253 if (nodeInfoMirror != null) {
244 254 nodeData.setShortName(Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"));
245 splitted.add(copy); 255 }
246 } 256
247 257 nodeData.setAssumptions(new ArrayList<>(assumptionsList));
248 node.setSpecializations(new ArrayList<SpecializationData>()); 258 nodeData.setNodeType(nodeType);
249 node.setSpecializationListeners(new ArrayList<SpecializationListenerData>()); 259 AnnotationMirror nodeContainer = findFirstAnnotation(lookupTypes, NodeContainer.class);
250 node.setCasts(new ArrayList<CreateCastData>()); 260 nodeData.setNodeContainer(nodeContainer != null);
251 261 nodeData.setTypeSystem(typeSystem);
252 return splitted; 262 nodeData.setFields(parseFields(elements));
253 } 263 parsedNodes.put(Utils.getQualifiedName(templateType), nodeData);
254 264 // parseChildren invokes cyclic parsing.
255 private static <M extends TemplateMethod> SortedMap<String, List<M>> groupByNodeId(List<M> methods) { 265 nodeData.setChildren(parseChildren(elements, lookupTypes));
256 SortedMap<String, List<M>> grouped = new TreeMap<>(); 266 nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
257 for (M m : methods) { 267
258 List<M> list = grouped.get(m.getId()); 268 return nodeData;
259 if (list == null) { 269 }
260 list = new ArrayList<>(); 270
261 grouped.put(m.getId(), list); 271 private static List<NodeFieldData> parseFields(List<? extends Element> elements) {
262 } 272 List<NodeFieldData> fields = new ArrayList<>();
263 list.add(m); 273 for (VariableElement field : ElementFilter.fieldsIn(elements)) {
264 } 274 if (field.getModifiers().contains(Modifier.STATIC)) {
265 return grouped; 275 continue;
276 }
277 if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) {
278 fields.add(new NodeFieldData(field));
279 }
280 }
281 return fields;
282 }
283
284 private List<NodeChildData> parseChildren(List<? extends Element> elements, final List<TypeElement> typeHierarchy) {
285 Set<String> shortCircuits = new HashSet<>();
286 for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
287 AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
288 if (mirror != null) {
289 shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value"));
290 }
291 }
292 Map<String, TypeMirror> castNodeTypes = new HashMap<>();
293 for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
294 AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, CreateCast.class);
295 if (mirror != null) {
296 List<String> children = (Utils.getAnnotationValueList(String.class, mirror, "value"));
297 if (children != null) {
298 for (String child : children) {
299 castNodeTypes.put(child, method.getReturnType());
300 }
301 }
302 }
303 }
304
305 List<NodeChildData> parsedChildren = new ArrayList<>();
306 List<TypeElement> typeHierarchyReversed = new ArrayList<>(typeHierarchy);
307 Collections.reverse(typeHierarchyReversed);
308 for (TypeElement type : typeHierarchyReversed) {
309 AnnotationMirror nodeClassMirror = Utils.findAnnotationMirror(processingEnv, type, NodeContainer.class);
310 AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, type, NodeChildren.class);
311
312 TypeMirror nodeClassType = type.getSuperclass();
313 if (!Utils.isAssignable(context, nodeClassType, context.getTruffleTypes().getNode())) {
314 nodeClassType = null;
315 }
316
317 if (nodeClassMirror != null) {
318 nodeClassType = inheritType(nodeClassMirror, "value", nodeClassType);
319 }
320
321 List<AnnotationMirror> children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class);
322 int index = 0;
323 for (AnnotationMirror childMirror : children) {
324 String name = Utils.getAnnotationValue(String.class, childMirror, "value");
325 if (name.equals("")) {
326 name = "child" + index;
327 }
328
329 Cardinality cardinality = Cardinality.ONE;
330
331 TypeMirror childType = inheritType(childMirror, "type", nodeClassType);
332 if (childType.getKind() == TypeKind.ARRAY) {
333 cardinality = Cardinality.MANY;
334 }
335
336 TypeMirror originalChildType = childType;
337 TypeMirror castNodeType = castNodeTypes.get(name);
338 if (castNodeType != null) {
339 childType = castNodeType;
340 }
341
342 Element getter = findGetter(elements, name, childType);
343
344 ExecutionKind kind = ExecutionKind.DEFAULT;
345 if (shortCircuits.contains(name)) {
346 kind = ExecutionKind.SHORT_CIRCUIT;
347 }
348
349 NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality, kind);
350
351 parsedChildren.add(nodeChild);
352
353 verifyNodeChild(nodeChild);
354 if (nodeChild.hasErrors()) {
355 continue;
356 }
357
358 NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(childType));
359 nodeChild.setNode(fieldNodeData);
360 if (fieldNodeData == null) {
361 nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(childType));
362 }
363
364 }
365 index++;
366 }
367
368 List<NodeChildData> filteredChildren = new ArrayList<>();
369 Set<String> encounteredNames = new HashSet<>();
370 for (int i = parsedChildren.size() - 1; i >= 0; i--) {
371 NodeChildData child = parsedChildren.get(i);
372 if (!encounteredNames.contains(child.getName())) {
373 filteredChildren.add(0, child);
374 encounteredNames.add(child.getName());
375 }
376 }
377
378 for (NodeChildData child : filteredChildren) {
379 List<String> executeWithStrings = Utils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith");
380 AnnotationValue executeWithValue = Utils.getAnnotationValue(child.getMessageAnnotation(), "executeWith");
381 List<NodeChildData> executeWith = new ArrayList<>();
382 for (String executeWithString : executeWithStrings) {
383
384 if (child.getName().equals(executeWithString)) {
385 child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString);
386 continue;
387 }
388
389 NodeChildData found = null;
390 boolean before = true;
391 for (NodeChildData resolveChild : filteredChildren) {
392 if (resolveChild == child) {
393 before = false;
394 continue;
395 }
396 if (resolveChild.getName().equals(executeWithString)) {
397 found = resolveChild;
398 break;
399 }
400 }
401
402 if (found == null) {
403 child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString);
404 continue;
405 } else if (!before) {
406 child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString,
407 executeWithString);
408 continue;
409 }
410 executeWith.add(found);
411 }
412 child.setExecuteWith(executeWith);
413 if (child.getNodeData() == null) {
414 continue;
415 }
416
417 List<ExecutableTypeData> types = child.findGenericExecutableTypes(context);
418 if (types.isEmpty()) {
419 child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", executeWith.size(), Utils.getSimpleName(child.getNodeType()));
420 continue;
421 }
422 }
423
424 return filteredChildren;
266 } 425 }
267 426
268 private void parseMethods(final NodeData node, List<Element> elements) { 427 private void parseMethods(final NodeData node, List<Element> elements) {
269 node.setShortCircuits(new ShortCircuitParser(context, node).parse(elements)); 428 node.setShortCircuits(new ShortCircuitParser(context, node).parse(elements));
270 node.setSpecializationListeners(new SpecializationListenerParser(context, node).parse(elements)); 429 node.setSpecializationListeners(new SpecializationListenerParser(context, node).parse(elements));
275 List<SpecializationData> allSpecializations = new ArrayList<>(); 434 List<SpecializationData> allSpecializations = new ArrayList<>();
276 allSpecializations.addAll(generics); 435 allSpecializations.addAll(generics);
277 allSpecializations.addAll(specializations); 436 allSpecializations.addAll(specializations);
278 437
279 node.setSpecializations(allSpecializations); 438 node.setSpecializations(allSpecializations);
439 }
440
441 private static List<NodeData> splitNodeData(NodeData node) {
442 SortedMap<String, List<SpecializationData>> groupedSpecializations = groupByNodeId(node.getSpecializations());
443 SortedMap<String, List<SpecializationListenerData>> groupedListeners = groupByNodeId(node.getSpecializationListeners());
444 SortedMap<String, List<CreateCastData>> groupedCasts = groupByNodeId(node.getCasts());
445
446 Set<String> ids = new TreeSet<>();
447 ids.addAll(groupedSpecializations.keySet());
448 ids.addAll(groupedListeners.keySet());
449
450 List<NodeData> splitted = new ArrayList<>();
451 for (String id : ids) {
452 List<SpecializationData> specializations = groupedSpecializations.get(id);
453 List<SpecializationListenerData> listeners = groupedListeners.get(id);
454 List<CreateCastData> casts = groupedCasts.get(id);
455
456 if (specializations == null) {
457 specializations = new ArrayList<>();
458 }
459
460 if (listeners == null) {
461 listeners = new ArrayList<>();
462 }
463
464 String nodeId = node.getNodeId();
465 if (nodeId.endsWith("Node") && !nodeId.equals("Node")) {
466 nodeId = nodeId.substring(0, nodeId.length() - 4);
467 }
468 String newNodeId = nodeId + Utils.firstLetterUpperCase(id);
469 NodeData copy = new NodeData(node, id, newNodeId);
470
471 copy.setSpecializations(specializations);
472 copy.setSpecializationListeners(listeners);
473 copy.setCasts(casts);
474
475 splitted.add(copy);
476 }
477
478 node.setSpecializations(new ArrayList<SpecializationData>());
479 node.setSpecializationListeners(new ArrayList<SpecializationListenerData>());
480 node.setCasts(new ArrayList<CreateCastData>());
481
482 return splitted;
280 } 483 }
281 484
282 private void finalizeSpecializations(List<Element> elements, final NodeData node) { 485 private void finalizeSpecializations(List<Element> elements, final NodeData node) {
283 List<SpecializationData> specializations = new ArrayList<>(node.getSpecializations()); 486 List<SpecializationData> specializations = new ArrayList<>(node.getSpecializations());
284 487
392 needsId.get(i).setId(ids.get(i)); 595 needsId.get(i).setId(ids.get(i));
393 } 596 }
394 } 597 }
395 } 598 }
396 599
600 private void assignShortCircuitsToSpecializations(NodeData node) {
601 Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
602
603 boolean valid = true;
604 for (NodeChildData field : node.filterFields(ExecutionKind.SHORT_CIRCUIT)) {
605 String valueName = field.getName();
606 List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
607
608 if (availableCircuits == null || availableCircuits.isEmpty()) {
609 node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
610 valid = false;
611 continue;
612 }
613
614 boolean sameMethodName = true;
615 String methodName = availableCircuits.get(0).getMethodName();
616 for (ShortCircuitData circuit : availableCircuits) {
617 if (!circuit.getMethodName().equals(methodName)) {
618 sameMethodName = false;
619 }
620 }
621
622 if (!sameMethodName) {
623 for (ShortCircuitData circuit : availableCircuits) {
624 circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName);
625 }
626 valid = false;
627 continue;
628 }
629
630 ShortCircuitData genericCircuit = null;
631 for (ShortCircuitData circuit : availableCircuits) {
632 if (isGenericShortCutMethod(node, circuit)) {
633 genericCircuit = circuit;
634 break;
635 }
636 }
637
638 if (genericCircuit == null) {
639 node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
640 valid = false;
641 continue;
642 }
643
644 for (ShortCircuitData circuit : availableCircuits) {
645 if (circuit != genericCircuit) {
646 circuit.setGenericShortCircuitMethod(genericCircuit);
647 }
648 }
649 }
650
651 if (!valid) {
652 return;
653 }
654
655 NodeChildData[] fields = node.filterFields(ExecutionKind.SHORT_CIRCUIT);
656 for (SpecializationData specialization : node.getSpecializations()) {
657 List<ShortCircuitData> assignedShortCuts = new ArrayList<>(fields.length);
658
659 for (int i = 0; i < fields.length; i++) {
660 List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(fields[i].getName());
661
662 ShortCircuitData genericShortCircuit = null;
663 ShortCircuitData compatibleShortCircuit = null;
664 for (ShortCircuitData circuit : availableShortCuts) {
665 if (circuit.isGeneric()) {
666 genericShortCircuit = circuit;
667 } else if (circuit.isCompatibleTo(specialization)) {
668 compatibleShortCircuit = circuit;
669 }
670 }
671
672 if (compatibleShortCircuit == null) {
673 compatibleShortCircuit = genericShortCircuit;
674 }
675 assignedShortCuts.add(compatibleShortCircuit);
676 }
677 specialization.setShortCircuits(assignedShortCuts);
678 }
679 }
680
397 private void matchGuards(List<Element> elements, SpecializationData specialization) { 681 private void matchGuards(List<Element> elements, SpecializationData specialization) {
398 if (specialization.getGuardDefinitions().isEmpty()) { 682 if (specialization.getGuardDefinitions().isEmpty()) {
399 specialization.setGuards(Collections.<GuardData> emptyList()); 683 specialization.setGuards(Collections.<GuardData> emptyList());
400 return; 684 return;
401 } 685 }
544 verifyNamingConvention(nodeData.getShortCircuits(), "needs"); 828 verifyNamingConvention(nodeData.getShortCircuits(), "needs");
545 829
546 verifySpecializationThrows(nodeData); 830 verifySpecializationThrows(nodeData);
547 } 831 }
548 832
549 private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List<? extends Element> elements, List<TypeElement> lookupTypes) { 833 private static void verifyNodeChild(NodeChildData nodeChild) {
550 NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString()); 834 if (nodeChild.getNodeType() == null) {
551 835 nodeChild.addError("No valid node type could be resoleved.");
552 AnnotationMirror typeSystemMirror = findFirstAnnotation(lookupTypes, TypeSystemReference.class); 836 }
553 if (typeSystemMirror == null) { 837 // FIXME verify node child
554 nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(nodeType)); 838 // FIXME verify node type set
555 return nodeData;
556 }
557
558 TypeMirror typeSytemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value");
559 final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true);
560 if (typeSystem == null) {
561 nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSytemType));
562 return nodeData;
563 }
564
565 boolean splitByMethodName = false;
566 AnnotationMirror nodeClass = findFirstAnnotation(lookupTypes, NodeClass.class);
567 if (nodeClass != null) {
568 splitByMethodName = Utils.getAnnotationValue(Boolean.class, nodeClass, "splitByMethodName");
569 }
570
571 List<String> assumptionsList = new ArrayList<>();
572
573 for (int i = lookupTypes.size() - 1; i >= 0; i--) {
574 TypeElement type = lookupTypes.get(i);
575 AnnotationMirror assumptions = Utils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class);
576 if (assumptions != null) {
577 List<String> assumptionStrings = Utils.getAnnotationValueList(String.class, assumptions, "value");
578 for (String string : assumptionStrings) {
579 if (assumptionsList.contains(string)) {
580 assumptionsList.remove(string);
581 }
582 assumptionsList.add(string);
583 }
584 }
585 }
586 AnnotationMirror nodeInfoMirror = findFirstAnnotation(lookupTypes, NodeInfo.class);
587 if (nodeInfoMirror != null) {
588 nodeData.setShortName(Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"));
589 }
590
591 nodeData.setAssumptions(new ArrayList<>(assumptionsList));
592 nodeData.setNodeType(nodeType);
593 nodeData.setSplitByMethodName(splitByMethodName);
594 nodeData.setTypeSystem(typeSystem);
595 nodeData.setFields(parseFields(elements));
596 parsedNodes.put(Utils.getQualifiedName(templateType), nodeData);
597 // parseChildren invokes cyclic parsing.
598 nodeData.setChildren(parseChildren(elements, lookupTypes));
599 nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
600
601 return nodeData;
602 }
603
604 private static boolean verifySpecializationParameters(NodeData nodeData) {
605 boolean valid = true;
606 int args = -1;
607 for (SpecializationData specializationData : nodeData.getSpecializations()) {
608 int signatureArgs = 0;
609 for (ActualParameter param : specializationData.getParameters()) {
610 if (param.getSpecification().isSignature()) {
611 signatureArgs++;
612 }
613 }
614 if (args != -1 && args != signatureArgs) {
615 valid = false;
616 break;
617 }
618 args = signatureArgs;
619 }
620 if (!valid) {
621 for (SpecializationData specialization : nodeData.getSpecializations()) {
622 specialization.addError("All specializations must have the same number of arguments.");
623 }
624 }
625 return valid;
626 } 839 }
627 840
628 private static void verifyMissingAbstractMethods(NodeData nodeData, List<? extends Element> originalElements) { 841 private static void verifyMissingAbstractMethods(NodeData nodeData, List<? extends Element> originalElements) {
629 if (!nodeData.needsFactory()) { 842 if (!nodeData.needsFactory()) {
630 // missing abstract methods only needs to be implemented 843 // missing abstract methods only needs to be implemented
689 902
690 // not found 903 // not found
691 nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type)); 904 nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type));
692 } 905 }
693 906
694 private static Map<Integer, List<ExecutableTypeData>> groupExecutableTypes(List<ExecutableTypeData> executableTypes) { 907 private static boolean verifySpecializationParameters(NodeData nodeData) {
695 Map<Integer, List<ExecutableTypeData>> groupedTypes = new HashMap<>();
696 for (ExecutableTypeData type : executableTypes) {
697 int evaluatedCount = type.getEvaluatedCount();
698
699 List<ExecutableTypeData> types = groupedTypes.get(evaluatedCount);
700 if (types == null) {
701 types = new ArrayList<>();
702 groupedTypes.put(evaluatedCount, types);
703 }
704 types.add(type);
705 }
706
707 for (List<ExecutableTypeData> types : groupedTypes.values()) {
708 Collections.sort(types);
709 }
710 return groupedTypes;
711 }
712
713 private AnnotationMirror findFirstAnnotation(List<? extends Element> elements, Class<? extends Annotation> annotation) {
714 for (Element element : elements) {
715 AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, element, annotation);
716 if (mirror != null) {
717 return mirror;
718 }
719 }
720 return null;
721 }
722
723 private static List<NodeFieldData> parseFields(List<? extends Element> elements) {
724 List<NodeFieldData> fields = new ArrayList<>();
725 for (VariableElement field : ElementFilter.fieldsIn(elements)) {
726 if (field.getModifiers().contains(Modifier.STATIC)) {
727 continue;
728 }
729 if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) {
730 fields.add(new NodeFieldData(field));
731 }
732 }
733 return fields;
734 }
735
736 private List<NodeChildData> parseChildren(List<? extends Element> elements, final List<TypeElement> typeHierarchy) {
737 Set<String> shortCircuits = new HashSet<>();
738 for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
739 AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
740 if (mirror != null) {
741 shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value"));
742 }
743 }
744 Map<String, TypeMirror> castNodeTypes = new HashMap<>();
745 for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
746 AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, CreateCast.class);
747 if (mirror != null) {
748 List<String> children = (Utils.getAnnotationValueList(String.class, mirror, "value"));
749 if (children != null) {
750 for (String child : children) {
751 castNodeTypes.put(child, method.getReturnType());
752 }
753 }
754 }
755 }
756
757 List<NodeChildData> parsedChildren = new ArrayList<>();
758 List<TypeElement> typeHierarchyReversed = new ArrayList<>(typeHierarchy);
759 Collections.reverse(typeHierarchyReversed);
760 for (TypeElement type : typeHierarchyReversed) {
761 AnnotationMirror nodeClassMirror = Utils.findAnnotationMirror(processingEnv, type, NodeClass.class);
762 AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, type, NodeChildren.class);
763
764 TypeMirror nodeClassType = type.getSuperclass();
765 if (!Utils.isAssignable(context, nodeClassType, context.getTruffleTypes().getNode())) {
766 nodeClassType = null;
767 }
768
769 if (nodeClassMirror != null) {
770 nodeClassType = inheritType(nodeClassMirror, "value", nodeClassType);
771 }
772
773 List<AnnotationMirror> children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class);
774 int index = 0;
775 for (AnnotationMirror childMirror : children) {
776 String name = Utils.getAnnotationValue(String.class, childMirror, "value");
777 if (name.equals("")) {
778 name = "child" + index;
779 }
780
781 Cardinality cardinality = Cardinality.ONE;
782
783 TypeMirror childType = inheritType(childMirror, "type", nodeClassType);
784 if (childType.getKind() == TypeKind.ARRAY) {
785 cardinality = Cardinality.MANY;
786 }
787
788 TypeMirror originalChildType = childType;
789 TypeMirror castNodeType = castNodeTypes.get(name);
790 if (castNodeType != null) {
791 childType = castNodeType;
792 }
793
794 Element getter = findGetter(elements, name, childType);
795
796 ExecutionKind kind = ExecutionKind.DEFAULT;
797 if (shortCircuits.contains(name)) {
798 kind = ExecutionKind.SHORT_CIRCUIT;
799 }
800
801 NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality, kind);
802
803 parsedChildren.add(nodeChild);
804
805 verifyNodeChild(nodeChild);
806 if (nodeChild.hasErrors()) {
807 continue;
808 }
809
810 NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(childType));
811 nodeChild.setNode(fieldNodeData);
812 if (fieldNodeData == null) {
813 nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(childType));
814 }
815
816 }
817 index++;
818 }
819
820 List<NodeChildData> filteredChildren = new ArrayList<>();
821 Set<String> encounteredNames = new HashSet<>();
822 for (int i = parsedChildren.size() - 1; i >= 0; i--) {
823 NodeChildData child = parsedChildren.get(i);
824 if (!encounteredNames.contains(child.getName())) {
825 filteredChildren.add(0, child);
826 encounteredNames.add(child.getName());
827 }
828 }
829
830 for (NodeChildData child : filteredChildren) {
831 List<String> executeWithStrings = Utils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith");
832 AnnotationValue executeWithValue = Utils.getAnnotationValue(child.getMessageAnnotation(), "executeWith");
833 List<NodeChildData> executeWith = new ArrayList<>();
834 for (String executeWithString : executeWithStrings) {
835
836 if (child.getName().equals(executeWithString)) {
837 child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString);
838 continue;
839 }
840
841 NodeChildData found = null;
842 boolean before = true;
843 for (NodeChildData resolveChild : filteredChildren) {
844 if (resolveChild == child) {
845 before = false;
846 continue;
847 }
848 if (resolveChild.getName().equals(executeWithString)) {
849 found = resolveChild;
850 break;
851 }
852 }
853
854 if (found == null) {
855 child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString);
856 continue;
857 } else if (!before) {
858 child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString,
859 executeWithString);
860 continue;
861 }
862 executeWith.add(found);
863 }
864 child.setExecuteWith(executeWith);
865 if (child.getNodeData() == null) {
866 continue;
867 }
868
869 List<ExecutableTypeData> types = child.findGenericExecutableTypes(context);
870 if (types.isEmpty()) {
871 child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", executeWith.size(), Utils.getSimpleName(child.getNodeType()));
872 continue;
873 }
874 }
875
876 return filteredChildren;
877 }
878
879 private static void verifyNodeChild(NodeChildData nodeChild) {
880 if (nodeChild.getNodeType() == null) {
881 nodeChild.addError("No valid node type could be resoleved.");
882 }
883 // FIXME verify node child
884 // FIXME verify node type set
885 }
886
887 private TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) {
888 TypeMirror inhertNodeType = context.getType(InheritNode.class);
889 TypeMirror value = Utils.getAnnotationValue(TypeMirror.class, annotation, valueName);
890 if (Utils.typeEquals(inhertNodeType, value)) {
891 return parentType;
892 } else {
893 return value;
894 }
895 }
896
897 private Element findGetter(List<? extends Element> elements, String variableName, TypeMirror type) {
898 if (type == null) {
899 return null;
900 }
901 String methodName;
902 if (Utils.typeEquals(type, context.getType(boolean.class))) {
903 methodName = "is" + Utils.firstLetterUpperCase(variableName);
904 } else {
905 methodName = "get" + Utils.firstLetterUpperCase(variableName);
906 }
907
908 for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
909 if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.isAssignable(context, type, method.getReturnType())) {
910 return method;
911 }
912 }
913 return null;
914 }
915
916 private void assignShortCircuitsToSpecializations(NodeData node) {
917 Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
918
919 boolean valid = true; 908 boolean valid = true;
920 for (NodeChildData field : node.filterFields(ExecutionKind.SHORT_CIRCUIT)) { 909 int args = -1;
921 String valueName = field.getName(); 910 for (SpecializationData specializationData : nodeData.getSpecializations()) {
922 List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName); 911 int signatureArgs = 0;
923 912 for (ActualParameter param : specializationData.getParameters()) {
924 if (availableCircuits == null || availableCircuits.isEmpty()) { 913 if (param.getSpecification().isSignature()) {
925 node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName); 914 signatureArgs++;
915 }
916 }
917 if (args != -1 && args != signatureArgs) {
926 valid = false; 918 valid = false;
927 continue; 919 break;
928 } 920 }
929 921 args = signatureArgs;
930 boolean sameMethodName = true; 922 }
931 String methodName = availableCircuits.get(0).getMethodName();
932 for (ShortCircuitData circuit : availableCircuits) {
933 if (!circuit.getMethodName().equals(methodName)) {
934 sameMethodName = false;
935 }
936 }
937
938 if (!sameMethodName) {
939 for (ShortCircuitData circuit : availableCircuits) {
940 circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName);
941 }
942 valid = false;
943 continue;
944 }
945
946 ShortCircuitData genericCircuit = null;
947 for (ShortCircuitData circuit : availableCircuits) {
948 if (isGenericShortCutMethod(node, circuit)) {
949 genericCircuit = circuit;
950 break;
951 }
952 }
953
954 if (genericCircuit == null) {
955 node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
956 valid = false;
957 continue;
958 }
959
960 for (ShortCircuitData circuit : availableCircuits) {
961 if (circuit != genericCircuit) {
962 circuit.setGenericShortCircuitMethod(genericCircuit);
963 }
964 }
965 }
966
967 if (!valid) { 923 if (!valid) {
968 return; 924 for (SpecializationData specialization : nodeData.getSpecializations()) {
969 } 925 specialization.addError("All specializations must have the same number of arguments.");
970 926 }
971 NodeChildData[] fields = node.filterFields(ExecutionKind.SHORT_CIRCUIT); 927 }
972 for (SpecializationData specialization : node.getSpecializations()) { 928 return valid;
973 List<ShortCircuitData> assignedShortCuts = new ArrayList<>(fields.length);
974
975 for (int i = 0; i < fields.length; i++) {
976 List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(fields[i].getName());
977
978 ShortCircuitData genericShortCircuit = null;
979 ShortCircuitData compatibleShortCircuit = null;
980 for (ShortCircuitData circuit : availableShortCuts) {
981 if (circuit.isGeneric()) {
982 genericShortCircuit = circuit;
983 } else if (circuit.isCompatibleTo(specialization)) {
984 compatibleShortCircuit = circuit;
985 }
986 }
987
988 if (compatibleShortCircuit == null) {
989 compatibleShortCircuit = genericShortCircuit;
990 }
991 assignedShortCuts.add(compatibleShortCircuit);
992 }
993 specialization.setShortCircuits(assignedShortCuts);
994 }
995 }
996
997 private static void verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) {
998 for (int i = 0; i < methods.size(); i++) {
999 TemplateMethod m1 = methods.get(i);
1000 if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
1001 m1.addError("Naming convention: method name must start with '%s'.", prefix);
1002 }
1003 }
1004 }
1005
1006 private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) {
1007 for (ActualParameter parameter : method.getParameters()) {
1008 NodeChildData field = node.findChild(parameter.getSpecification().getName());
1009 if (field == null) {
1010 continue;
1011 }
1012 ExecutableTypeData found = null;
1013 List<ExecutableTypeData> executableElements = field.findGenericExecutableTypes(context);
1014 for (ExecutableTypeData executable : executableElements) {
1015 if (executable.getType().equalsType(parameter.getTypeSystemType())) {
1016 found = executable;
1017 break;
1018 }
1019 }
1020 if (found == null) {
1021 return false;
1022 }
1023 }
1024 return true;
1025 }
1026
1027 private static Map<String, List<ShortCircuitData>> groupShortCircuits(List<ShortCircuitData> shortCircuits) {
1028 Map<String, List<ShortCircuitData>> group = new HashMap<>();
1029 for (ShortCircuitData shortCircuit : shortCircuits) {
1030 List<ShortCircuitData> circuits = group.get(shortCircuit.getValueName());
1031 if (circuits == null) {
1032 circuits = new ArrayList<>();
1033 group.put(shortCircuit.getValueName(), circuits);
1034 }
1035 circuits.add(shortCircuit);
1036 }
1037 return group;
1038 }
1039
1040 private static List<TypeElement> findSuperClasses(List<TypeElement> collection, TypeElement element) {
1041 if (element.getSuperclass() != null) {
1042 TypeElement superElement = Utils.fromTypeMirror(element.getSuperclass());
1043 if (superElement != null) {
1044 findSuperClasses(collection, superElement);
1045 }
1046 }
1047 collection.add(element);
1048 return collection;
1049 } 929 }
1050 930
1051 private static void verifySpecializationOrder(NodeData node) { 931 private static void verifySpecializationOrder(NodeData node) {
1052 List<SpecializationData> specializations = node.getSpecializations(); 932 List<SpecializationData> specializations = node.getSpecializations();
1053 for (int i = 0; i < specializations.size(); i++) { 933 for (int i = 0; i < specializations.size(); i++) {
1092 } 972 }
1093 } 973 }
1094 } 974 }
1095 } 975 }
1096 976
1097 @Override 977 private static void verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) {
1098 public Class<? extends Annotation> getAnnotationType() { 978 for (int i = 0; i < methods.size(); i++) {
979 TemplateMethod m1 = methods.get(i);
980 if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
981 m1.addError("Naming convention: method name must start with '%s'.", prefix);
982 }
983 }
984 }
985
986 private static Map<Integer, List<ExecutableTypeData>> groupExecutableTypes(List<ExecutableTypeData> executableTypes) {
987 Map<Integer, List<ExecutableTypeData>> groupedTypes = new HashMap<>();
988 for (ExecutableTypeData type : executableTypes) {
989 int evaluatedCount = type.getEvaluatedCount();
990
991 List<ExecutableTypeData> types = groupedTypes.get(evaluatedCount);
992 if (types == null) {
993 types = new ArrayList<>();
994 groupedTypes.put(evaluatedCount, types);
995 }
996 types.add(type);
997 }
998
999 for (List<ExecutableTypeData> types : groupedTypes.values()) {
1000 Collections.sort(types);
1001 }
1002 return groupedTypes;
1003 }
1004
1005 private AnnotationMirror findFirstAnnotation(List<? extends Element> elements, Class<? extends Annotation> annotation) {
1006 for (Element element : elements) {
1007 AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, element, annotation);
1008 if (mirror != null) {
1009 return mirror;
1010 }
1011 }
1099 return null; 1012 return null;
1100 } 1013 }
1101 1014
1102 @Override 1015 private TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) {
1103 public List<Class<? extends Annotation>> getTypeDelegatedAnnotationTypes() { 1016 TypeMirror inhertNodeType = context.getTruffleTypes().getNode();
1104 return ANNOTATIONS; 1017 TypeMirror value = Utils.getAnnotationValue(TypeMirror.class, annotation, valueName);
1018 if (Utils.typeEquals(inhertNodeType, value)) {
1019 return parentType;
1020 } else {
1021 return value;
1022 }
1023 }
1024
1025 private Element findGetter(List<? extends Element> elements, String variableName, TypeMirror type) {
1026 if (type == null) {
1027 return null;
1028 }
1029 String methodName;
1030 if (Utils.typeEquals(type, context.getType(boolean.class))) {
1031 methodName = "is" + Utils.firstLetterUpperCase(variableName);
1032 } else {
1033 methodName = "get" + Utils.firstLetterUpperCase(variableName);
1034 }
1035
1036 for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
1037 if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.isAssignable(context, type, method.getReturnType())) {
1038 return method;
1039 }
1040 }
1041 return null;
1042 }
1043
1044 private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) {
1045 for (ActualParameter parameter : method.getParameters()) {
1046 NodeChildData field = node.findChild(parameter.getSpecification().getName());
1047 if (field == null) {
1048 continue;
1049 }
1050 ExecutableTypeData found = null;
1051 List<ExecutableTypeData> executableElements = field.findGenericExecutableTypes(context);
1052 for (ExecutableTypeData executable : executableElements) {
1053 if (executable.getType().equalsType(parameter.getTypeSystemType())) {
1054 found = executable;
1055 break;
1056 }
1057 }
1058 if (found == null) {
1059 return false;
1060 }
1061 }
1062 return true;
1063 }
1064
1065 private static Map<String, List<ShortCircuitData>> groupShortCircuits(List<ShortCircuitData> shortCircuits) {
1066 Map<String, List<ShortCircuitData>> group = new HashMap<>();
1067 for (ShortCircuitData shortCircuit : shortCircuits) {
1068 List<ShortCircuitData> circuits = group.get(shortCircuit.getValueName());
1069 if (circuits == null) {
1070 circuits = new ArrayList<>();
1071 group.put(shortCircuit.getValueName(), circuits);
1072 }
1073 circuits.add(shortCircuit);
1074 }
1075 return group;
1076 }
1077
1078 private static <M extends TemplateMethod> SortedMap<String, List<M>> groupByNodeId(List<M> methods) {
1079 SortedMap<String, List<M>> grouped = new TreeMap<>();
1080 for (M m : methods) {
1081 List<M> list = grouped.get(m.getId());
1082 if (list == null) {
1083 list = new ArrayList<>();
1084 grouped.put(m.getId(), list);
1085 }
1086 list.add(m);
1087 }
1088 return grouped;
1089 }
1090
1091 private static List<TypeElement> findSuperClasses(List<TypeElement> collection, TypeElement element) {
1092 if (element.getSuperclass() != null) {
1093 TypeElement superElement = Utils.fromTypeMirror(element.getSuperclass());
1094 if (superElement != null) {
1095 findSuperClasses(collection, superElement);
1096 }
1097 }
1098 collection.add(element);
1099 return collection;
1105 } 1100 }
1106 1101
1107 } 1102 }