Mercurial > hg > graal-jvmci-8
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 } |