Mercurial > hg > truffle
comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java @ 20938:18c0f02fa4d2
Truffle-DSL: make type systems optional.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Tue, 14 Apr 2015 15:12:48 +0200 |
parents | 8dc73c226c63 |
children | 476374f3fe9a |
comparison
equal
deleted
inserted
replaced
20937:37ea76052733 | 20938:18c0f02fa4d2 |
---|---|
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.*; | 33 import com.oracle.truffle.api.*; |
34 import com.oracle.truffle.api.dsl.*; | 34 import com.oracle.truffle.api.dsl.*; |
35 import com.oracle.truffle.api.dsl.NodeField; | 35 import com.oracle.truffle.api.dsl.internal.*; |
36 import com.oracle.truffle.api.nodes.*; | 36 import com.oracle.truffle.api.nodes.*; |
37 import com.oracle.truffle.dsl.processor.*; | 37 import com.oracle.truffle.dsl.processor.*; |
38 import com.oracle.truffle.dsl.processor.expression.*; | 38 import com.oracle.truffle.dsl.processor.expression.*; |
39 import com.oracle.truffle.dsl.processor.java.*; | 39 import com.oracle.truffle.dsl.processor.java.*; |
40 import com.oracle.truffle.dsl.processor.java.compiler.*; | 40 import com.oracle.truffle.dsl.processor.java.compiler.*; |
43 import com.oracle.truffle.dsl.processor.model.*; | 43 import com.oracle.truffle.dsl.processor.model.*; |
44 import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality; | 44 import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality; |
45 import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind; | 45 import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind; |
46 import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature; | 46 import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature; |
47 | 47 |
48 @DSLOptions | |
48 public class NodeParser extends AbstractParser<NodeData> { | 49 public class NodeParser extends AbstractParser<NodeData> { |
49 | 50 |
50 public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Fallback.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class, | 51 public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Fallback.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class, |
51 NodeChildren.class); | 52 NodeChildren.class); |
52 | 53 |
143 return node; | 144 return node; |
144 } | 145 } |
145 | 146 |
146 node.getFields().addAll(parseFields(lookupTypes, members)); | 147 node.getFields().addAll(parseFields(lookupTypes, members)); |
147 node.getChildren().addAll(parseChildren(lookupTypes, members)); | 148 node.getChildren().addAll(parseChildren(lookupTypes, members)); |
148 node.getChildExecutions().addAll(parseExecutions(node.getChildren(), members)); | 149 node.getChildExecutions().addAll(parseExecutions(node.getFields(), node.getChildren(), members)); |
149 node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node, null, context.getFrameTypes()).parse(members))); | 150 node.setExecutableTypes(groupExecutableTypes(parseExecutableTypeData(members, node.getChildExecutions().size(), context.getFrameTypes()))); |
150 | 151 |
151 initializeExecutableTypes(node); | 152 initializeExecutableTypes(node); |
152 initializeImportGuards(node, lookupTypes, members); | 153 initializeImportGuards(node, lookupTypes, members); |
153 | 154 |
154 if (node.hasErrors()) { | 155 if (node.hasErrors()) { |
254 return members; | 255 return members; |
255 } | 256 } |
256 | 257 |
257 private NodeData parseNodeData(TypeElement templateType, List<TypeElement> typeHierarchy) { | 258 private NodeData parseNodeData(TypeElement templateType, List<TypeElement> typeHierarchy) { |
258 AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); | 259 AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); |
259 if (typeSystemMirror == null) { | 260 TypeSystemData typeSystem = null; |
260 NodeData nodeData = new NodeData(context, templateType); | 261 if (typeSystemMirror != null) { |
261 nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), ElementUtils.getQualifiedName(templateType)); | 262 TypeMirror typeSystemType = ElementUtils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value"); |
262 return nodeData; | 263 typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true); |
263 } | 264 if (typeSystem == null) { |
264 | 265 NodeData nodeData = new NodeData(context, templateType); |
265 TypeMirror typeSystemType = ElementUtils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value"); | 266 nodeData.addError("The used type system '%s' is invalid. Fix errors in the type system first.", ElementUtils.getQualifiedName(typeSystemType)); |
266 final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true); | 267 return nodeData; |
267 if (typeSystem == null) { | 268 } |
268 NodeData nodeData = new NodeData(context, templateType); | 269 } else { |
269 nodeData.addError("The used type system '%s' is invalid. Fix errors in the type system first.", ElementUtils.getQualifiedName(typeSystemType)); | 270 // default dummy type system |
270 return nodeData; | 271 typeSystem = new TypeSystemData(context, templateType, null, NodeParser.class.getAnnotation(DSLOptions.class), true); |
271 } | 272 } |
272 | |
273 AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class); | 273 AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class); |
274 String shortName = null; | 274 String shortName = null; |
275 if (nodeInfoMirror != null) { | 275 if (nodeInfoMirror != null) { |
276 shortName = ElementUtils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"); | 276 shortName = ElementUtils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"); |
277 } | 277 } |
404 } | 404 } |
405 | 405 |
406 return filteredChildren; | 406 return filteredChildren; |
407 } | 407 } |
408 | 408 |
409 private List<NodeExecutionData> parseExecutions(List<NodeChildData> children, List<? extends Element> elements) { | 409 private List<NodeExecutionData> parseExecutions(List<NodeFieldData> fields, List<NodeChildData> children, List<? extends Element> elements) { |
410 if (children == null) { | |
411 return null; | |
412 } | |
413 | |
414 // pre-parse short circuits | 410 // pre-parse short circuits |
415 Set<String> shortCircuits = new HashSet<>(); | 411 Set<String> shortCircuits = new HashSet<>(); |
416 List<ExecutableElement> methods = ElementFilter.methodsIn(elements); | 412 List<ExecutableElement> methods = ElementFilter.methodsIn(elements); |
417 for (ExecutableElement method : methods) { | 413 for (ExecutableElement method : methods) { |
418 AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, ShortCircuit.class); | 414 AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, ShortCircuit.class); |
431 } else { | 427 } else { |
432 maxSignatureSize = children.size(); | 428 maxSignatureSize = children.size(); |
433 } | 429 } |
434 } | 430 } |
435 | 431 |
432 List<NodeFieldData> nonGetterFields = new ArrayList<>(); | |
433 for (NodeFieldData field : fields) { | |
434 if (field.getGetter() == null && field.isGenerated()) { | |
435 nonGetterFields.add(field); | |
436 } | |
437 } | |
438 | |
436 TypeMirror cacheAnnotation = context.getType(Cached.class); | 439 TypeMirror cacheAnnotation = context.getType(Cached.class); |
437 List<TypeMirror> frameTypes = context.getFrameTypes(); | 440 List<TypeMirror> frameTypes = context.getFrameTypes(); |
438 // pre-parse specializations to find signature size | 441 // pre-parse specializations to find signature size |
439 for (ExecutableElement method : methods) { | 442 for (ExecutableElement method : methods) { |
440 AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class); | 443 AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class); |
441 if (mirror == null) { | 444 if (mirror == null) { |
442 continue; | 445 continue; |
443 } | 446 } |
444 int currentArgumentIndex = 0; | 447 int currentArgumentIndex = 0; |
445 boolean skipShortCircuit = false; | 448 boolean skipShortCircuit = false; |
446 outer: for (VariableElement var : method.getParameters()) { | 449 parameter: for (VariableElement var : method.getParameters()) { |
450 if (skipShortCircuit) { | |
451 skipShortCircuit = false; | |
452 continue parameter; | |
453 } | |
447 | 454 |
448 TypeMirror type = var.asType(); | 455 TypeMirror type = var.asType(); |
449 if (currentArgumentIndex == 0) { | 456 if (currentArgumentIndex == 0) { |
450 // skip optionals | 457 // skip optionals |
451 for (TypeMirror frameType : frameTypes) { | 458 for (TypeMirror frameType : frameTypes) { |
452 if (ElementUtils.typeEquals(type, frameType)) { | 459 if (ElementUtils.typeEquals(type, frameType)) { |
453 continue outer; | 460 continue parameter; |
454 } | 461 } |
455 } | 462 } |
456 } | 463 } |
457 | 464 |
465 if (currentArgumentIndex < nonGetterFields.size()) { | |
466 for (NodeFieldData field : nonGetterFields) { | |
467 if (ElementUtils.typeEquals(var.asType(), field.getType())) { | |
468 continue parameter; | |
469 } | |
470 } | |
471 } | |
472 | |
458 if (ElementUtils.findAnnotationMirror(var.getAnnotationMirrors(), cacheAnnotation) != null) { | 473 if (ElementUtils.findAnnotationMirror(var.getAnnotationMirrors(), cacheAnnotation) != null) { |
459 continue outer; | 474 continue parameter; |
460 } | 475 } |
461 | 476 |
462 int childIndex = currentArgumentIndex < children.size() ? currentArgumentIndex : children.size() - 1; | 477 int childIndex = currentArgumentIndex < children.size() ? currentArgumentIndex : children.size() - 1; |
463 if (childIndex == -1) { | 478 if (childIndex != -1) { |
464 continue; | |
465 } | |
466 if (!skipShortCircuit) { | |
467 NodeChildData child = children.get(childIndex); | 479 NodeChildData child = children.get(childIndex); |
468 if (shortCircuits.contains(NodeExecutionData.createIndexedName(child, currentArgumentIndex - childIndex))) { | 480 if (shortCircuits.contains(NodeExecutionData.createIndexedName(child, currentArgumentIndex - childIndex))) { |
469 skipShortCircuit = true; | 481 skipShortCircuit = true; |
470 continue; | |
471 } | 482 } |
472 } else { | |
473 skipShortCircuit = false; | |
474 } | 483 } |
475 | 484 |
476 currentArgumentIndex++; | 485 currentArgumentIndex++; |
477 } | 486 } |
478 maxSignatureSize = Math.max(maxSignatureSize, currentArgumentIndex); | 487 maxSignatureSize = Math.max(maxSignatureSize, currentArgumentIndex); |
479 } | 488 } |
480 | 489 |
481 List<NodeExecutionData> executions = new ArrayList<>(); | 490 List<NodeExecutionData> executions = new ArrayList<>(); |
482 for (int i = 0; i < maxSignatureSize; i++) { | 491 for (int i = 0; i < maxSignatureSize; i++) { |
492 boolean varArgParameter = false; | |
483 int childIndex = i; | 493 int childIndex = i; |
484 boolean varArg = false; | 494 if (i >= children.size() - 1) { |
485 if (childIndex >= children.size() - 1) { | |
486 if (hasVarArgs) { | 495 if (hasVarArgs) { |
487 childIndex = children.size() - 1; | 496 varArgParameter = hasVarArgs; |
488 varArg = hasVarArgs; | 497 childIndex = Math.min(i, children.size() - 1); |
489 } else if (childIndex >= children.size()) { | 498 } else if (i >= children.size()) { |
490 break; | 499 childIndex = -1; |
491 } | 500 } |
492 } | 501 } |
493 int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1; | 502 int varArgsIndex = -1; |
494 NodeChildData child = children.get(childIndex); | 503 boolean shortCircuit = false; |
495 boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createIndexedName(child, varArgsIndex)); | 504 NodeChildData child = null; |
496 executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit)); | 505 if (childIndex != -1) { |
506 varArgsIndex = varArgParameter ? Math.abs(childIndex - i) : -1; | |
507 child = children.get(childIndex); | |
508 shortCircuit = shortCircuits.contains(NodeExecutionData.createIndexedName(child, varArgsIndex)); | |
509 } | |
510 executions.add(new NodeExecutionData(child, i, varArgsIndex, shortCircuit)); | |
497 } | 511 } |
498 return executions; | 512 return executions; |
513 } | |
514 | |
515 private List<ExecutableTypeData> parseExecutableTypeData(List<? extends Element> elements, int signatureSize, List<TypeMirror> frameTypes) { | |
516 List<ExecutableTypeData> typeData = new ArrayList<>(); | |
517 for (ExecutableElement method : ElementFilter.methodsIn(elements)) { | |
518 Set<Modifier> modifiers = method.getModifiers(); | |
519 if (modifiers.contains(Modifier.PRIVATE) || modifiers.contains(Modifier.STATIC)) { | |
520 continue; | |
521 } | |
522 if (!method.getSimpleName().toString().startsWith("execute")) { | |
523 continue; | |
524 } | |
525 if (ElementUtils.findAnnotationMirror(context.getEnvironment(), method, Specialization.class) != null) { | |
526 continue; | |
527 } | |
528 | |
529 ExecutableTypeData executableType = new ExecutableTypeData(method, signatureSize, context.getFrameTypes()); | |
530 | |
531 if (executableType.getFrameParameter() != null) { | |
532 boolean supportedType = false; | |
533 for (TypeMirror type : frameTypes) { | |
534 if (ElementUtils.isAssignable(type, executableType.getFrameParameter())) { | |
535 supportedType = true; | |
536 break; | |
537 } | |
538 } | |
539 if (!supportedType) { | |
540 continue; | |
541 } | |
542 } | |
543 | |
544 typeData.add(executableType); | |
545 } | |
546 | |
547 Collections.sort(typeData); | |
548 return typeData; | |
499 } | 549 } |
500 | 550 |
501 private void initializeExecutableTypes(NodeData node) { | 551 private void initializeExecutableTypes(NodeData node) { |
502 List<ExecutableTypeData> allExecutes = node.getExecutableTypes(); | 552 List<ExecutableTypeData> allExecutes = node.getExecutableTypes(); |
503 | 553 |
505 TypeMirror frameType = null; | 555 TypeMirror frameType = null; |
506 Set<Integer> evaluatedCounts = new HashSet<>(); | 556 Set<Integer> evaluatedCounts = new HashSet<>(); |
507 for (ExecutableTypeData execute : allExecutes) { | 557 for (ExecutableTypeData execute : allExecutes) { |
508 evaluatedCounts.add(execute.getEvaluatedCount()); | 558 evaluatedCounts.add(execute.getEvaluatedCount()); |
509 | 559 |
510 Parameter frame = execute.getFrame(); | 560 TypeMirror frame = execute.getFrameParameter(); |
511 TypeMirror resolvedFrameType; | 561 TypeMirror resolvedFrameType; |
512 if (frame != null) { | 562 if (frame != null) { |
513 resolvedFrameType = frame.getType(); | 563 resolvedFrameType = frame; |
514 if (frameType == null) { | 564 if (frameType == null) { |
515 frameType = resolvedFrameType; | 565 frameType = resolvedFrameType; |
516 } else if (!ElementUtils.typeEquals(frameType, resolvedFrameType)) { | 566 } else if (!ElementUtils.typeEquals(frameType, resolvedFrameType)) { |
517 // found inconsistent frame types | 567 // found inconsistent frame types |
518 inconsistentFrameTypes.add(ElementUtils.getSimpleName(frameType)); | 568 inconsistentFrameTypes.add(ElementUtils.getSimpleName(frameType)); |
538 List<ExecutableTypeData> genericExecutes = node.findGenericExecutableTypes(context, evaluatedCount); | 588 List<ExecutableTypeData> genericExecutes = node.findGenericExecutableTypes(context, evaluatedCount); |
539 int genericCount = 0; | 589 int genericCount = 0; |
540 int voidCount = 0; | 590 int voidCount = 0; |
541 for (ExecutableTypeData executableTypeData : genericExecutes) { | 591 for (ExecutableTypeData executableTypeData : genericExecutes) { |
542 if (!executableTypeData.getMethod().getModifiers().contains(Modifier.FINAL)) { | 592 if (!executableTypeData.getMethod().getModifiers().contains(Modifier.FINAL)) { |
543 if (ElementUtils.isVoid(executableTypeData.getReturnType().getType())) { | 593 if (ElementUtils.isVoid(executableTypeData.getReturnType())) { |
544 voidCount++; | 594 voidCount++; |
545 } else { | 595 } else { |
546 genericCount++; | 596 genericCount++; |
547 } | 597 } |
548 } | 598 } |
550 // multiple generic execute | 600 // multiple generic execute |
551 if (evaluatedCount == 0) { | 601 if (evaluatedCount == 0) { |
552 if (voidCount > 1) { | 602 if (voidCount > 1) { |
553 List<String> methodSignatures = new ArrayList<>(); | 603 List<String> methodSignatures = new ArrayList<>(); |
554 for (ExecutableTypeData type : genericExecutes) { | 604 for (ExecutableTypeData type : genericExecutes) { |
555 if (type.getType().isVoid()) { | 605 if (context.isType(type.getReturnType(), void.class)) { |
556 methodSignatures.add(type.createReferenceName()); | 606 methodSignatures.add(ElementUtils.createReferenceName(type.getMethod())); |
557 } | 607 } |
558 } | 608 } |
559 node.addWarning("Multiple accessible and overridable generic execute methods found %s. Remove all but one or mark all but one as final.", methodSignatures); | 609 node.addWarning("Multiple accessible and overridable generic execute methods found %s. Remove all but one or mark all but one as final.", methodSignatures); |
560 } else if (genericCount > 1) { | 610 } else if (genericCount > 1) { |
561 List<String> methodSignatures = new ArrayList<>(); | 611 List<String> methodSignatures = new ArrayList<>(); |
562 for (ExecutableTypeData type : genericExecutes) { | 612 for (ExecutableTypeData type : genericExecutes) { |
563 if (!type.getType().isVoid()) { | 613 if (!context.isType(type.getReturnType(), void.class)) { |
564 methodSignatures.add(type.createReferenceName()); | 614 methodSignatures.add(ElementUtils.createReferenceName(type.getMethod())); |
565 } | 615 } |
566 } | 616 } |
567 node.addWarning("Multiple accessible and overridable generic execute methods found %s. Remove all but one or mark all but one as final.", methodSignatures); | 617 node.addWarning("Multiple accessible and overridable generic execute methods found %s. Remove all but one or mark all but one as final.", methodSignatures); |
568 } | 618 } |
569 } | 619 } |
575 if (totalGenericCount + totalVoidCount == 0) { | 625 if (totalGenericCount + totalVoidCount == 0) { |
576 node.addError("No accessible and overridable generic execute method found. Generic execute methods usually have the " | 626 node.addError("No accessible and overridable generic execute method found. Generic execute methods usually have the " |
577 + "signature 'public abstract {Type} execute(VirtualFrame)' and must not throw any checked exceptions."); | 627 + "signature 'public abstract {Type} execute(VirtualFrame)' and must not throw any checked exceptions."); |
578 } | 628 } |
579 | 629 |
630 int nodeChildDeclarations = 0; | |
631 int nodeChildDeclarationsRequired = 0; | |
632 List<NodeExecutionData> executions = node.getChildExecutions(); | |
633 for (NodeExecutionData execution : executions) { | |
634 if (execution.getChild() == null) { | |
635 nodeChildDeclarationsRequired = execution.getIndex() + 1; | |
636 } else { | |
637 nodeChildDeclarations++; | |
638 } | |
639 } | |
640 | |
641 List<String> requireNodeChildDeclarations = new ArrayList<>(); | |
642 for (ExecutableTypeData type : allExecutes) { | |
643 if (type.getEvaluatedCount() < nodeChildDeclarationsRequired) { | |
644 requireNodeChildDeclarations.add(ElementUtils.createReferenceName(type.getMethod())); | |
645 } | |
646 } | |
647 | |
648 if (!requireNodeChildDeclarations.isEmpty()) { | |
649 node.addError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. " | |
650 + "The following execute methods do not provide all evaluated values for the expected signature size %s: %s.", executions.size(), requireNodeChildDeclarations); | |
651 } | |
652 | |
653 if (nodeChildDeclarations > 0 && executions.size() == node.getMinimalEvaluatedParameters()) { | |
654 for (NodeChildData child : node.getChildren()) { | |
655 child.addError("Unnecessary @NodeChild declaration. All evaluated child values are provided as parameters in execute methods."); | |
656 } | |
657 } | |
658 | |
580 } | 659 } |
581 | 660 |
582 private static Map<Integer, List<ExecutableTypeData>> groupExecutableTypes(List<ExecutableTypeData> executableTypes) { | 661 private static Map<Integer, List<ExecutableTypeData>> groupExecutableTypes(List<ExecutableTypeData> executableTypes) { |
583 Map<Integer, List<ExecutableTypeData>> groupedTypes = new TreeMap<>(); | 662 Map<Integer, List<ExecutableTypeData>> groupedTypes = new TreeMap<>(); |
584 for (ExecutableTypeData type : executableTypes) { | 663 for (ExecutableTypeData type : executableTypes) { |
606 NodeData fieldNodeData = parseChildNodeData(node, child, ElementUtils.fromTypeMirror(nodeType)); | 685 NodeData fieldNodeData = parseChildNodeData(node, child, ElementUtils.fromTypeMirror(nodeType)); |
607 | 686 |
608 child.setNode(fieldNodeData); | 687 child.setNode(fieldNodeData); |
609 if (fieldNodeData == null || fieldNodeData.hasErrors()) { | 688 if (fieldNodeData == null || fieldNodeData.hasErrors()) { |
610 child.addError("Node type '%s' is invalid or not a subclass of Node.", ElementUtils.getQualifiedName(nodeType)); | 689 child.addError("Node type '%s' is invalid or not a subclass of Node.", ElementUtils.getQualifiedName(nodeType)); |
611 } else if (!ElementUtils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) { | |
612 child.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(), | |
613 NodeChild.class.getSimpleName(), ElementUtils.getSimpleName(node.getTypeSystem().getTemplateType()), | |
614 ElementUtils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType())); | |
615 } else { | 690 } else { |
616 List<ExecutableTypeData> types = child.findGenericExecutableTypes(context); | 691 List<ExecutableTypeData> types = child.findGenericExecutableTypes(context); |
617 if (types.isEmpty()) { | 692 if (types.isEmpty()) { |
618 AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith"); | 693 AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith"); |
619 child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s and frame types %s.", child.getExecuteWith().size(), | 694 child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s and frame types %s.", child.getExecuteWith().size(), |
678 List<? extends Element> members = processingEnv.getElementUtils().getAllMembers(templateType); | 753 List<? extends Element> members = processingEnv.getElementUtils().getAllMembers(templateType); |
679 NodeData node = parseNodeData(templateType, lookupTypes); | 754 NodeData node = parseNodeData(templateType, lookupTypes); |
680 if (node.hasErrors()) { | 755 if (node.hasErrors()) { |
681 return node; | 756 return node; |
682 } | 757 } |
683 node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node, child, createAllowedChildFrameTypes(parentNode)).parse(members))); | 758 List<TypeMirror> frameTypes = Collections.emptyList(); |
759 if (parentNode.getFrameType() != null) { | |
760 frameTypes = Arrays.asList(parentNode.getFrameType()); | |
761 } | |
762 node.setExecutableTypes(groupExecutableTypes(parseExecutableTypeData(members, child.getExecuteWith().size(), frameTypes))); | |
684 node.setFrameType(parentNode.getFrameType()); | 763 node.setFrameType(parentNode.getFrameType()); |
685 return node; | 764 return node; |
686 } | 765 } |
687 | 766 |
688 private List<TypeMirror> createAllowedChildFrameTypes(NodeData parentNode) { | 767 private List<TypeMirror> createAllowedChildFrameTypes(NodeData parentNode) { |
1157 MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null); | 1236 MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null); |
1158 | 1237 |
1159 List<VariableElement> parameterTypes = new ArrayList<>(); | 1238 List<VariableElement> parameterTypes = new ArrayList<>(); |
1160 int signatureIndex = 1; | 1239 int signatureIndex = 1; |
1161 for (ParameterSpec spec : specification.getRequired()) { | 1240 for (ParameterSpec spec : specification.getRequired()) { |
1162 parameterTypes.add(new CodeVariableElement(createGenericType(spec, node.getSpecializations(), signatureIndex), "arg" + signatureIndex)); | 1241 parameterTypes.add(new CodeVariableElement(createGenericType(node, spec), "arg" + signatureIndex)); |
1163 if (spec.isSignature()) { | 1242 if (spec.isSignature()) { |
1164 signatureIndex++; | 1243 signatureIndex++; |
1165 } | 1244 } |
1166 } | 1245 } |
1167 | 1246 |
1168 TypeMirror returnType = createGenericType(specification.getReturnType(), node.getSpecializations(), 0); | 1247 TypeMirror returnType = createGenericType(node, specification.getReturnType()); |
1169 SpecializationData generic = parser.create("Generic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, parameterTypes); | 1248 SpecializationData generic = parser.create("Generic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, parameterTypes); |
1170 if (generic == null) { | 1249 if (generic == null) { |
1171 throw new RuntimeException("Unable to create generic signature for node " + node.getNodeId() + " with " + parameterTypes + ". Specification " + specification + "."); | 1250 throw new RuntimeException("Unable to create generic signature for node " + node.getNodeId() + " with " + parameterTypes + ". Specification " + specification + "."); |
1172 } | 1251 } |
1173 | 1252 |
1174 return generic; | 1253 return generic; |
1175 } | 1254 } |
1176 | 1255 |
1177 private TypeMirror createGenericType(ParameterSpec spec, List<SpecializationData> specializations, int signatureIndex) { | 1256 private TypeMirror createGenericType(NodeData node, ParameterSpec spec) { |
1178 NodeExecutionData execution = spec.getExecution(); | 1257 NodeExecutionData execution = spec.getExecution(); |
1258 Collection<TypeMirror> allowedTypes; | |
1179 if (execution == null) { | 1259 if (execution == null) { |
1180 if (spec.getAllowedTypes().size() == 1) { | 1260 allowedTypes = spec.getAllowedTypes(); |
1181 return spec.getAllowedTypes().get(0); | |
1182 } else { | |
1183 return ElementUtils.getCommonSuperType(context, spec.getAllowedTypes().toArray(new TypeMirror[0])); | |
1184 } | |
1185 } else { | 1261 } else { |
1186 Set<TypeData> types = new HashSet<>(); | 1262 allowedTypes = node.getPossibleTypes(execution); |
1187 for (SpecializationData specialization : specializations) { | 1263 } |
1188 types.add(specialization.getTypeSignature().get(signatureIndex)); | 1264 if (allowedTypes.size() == 1) { |
1189 } | 1265 return allowedTypes.iterator().next(); |
1190 | 1266 } else { |
1191 NodeChildData child = execution.getChild(); | 1267 return ElementUtils.getCommonSuperType(context, allowedTypes.toArray(new TypeMirror[allowedTypes.size()])); |
1192 TypeData genericType = null; | 1268 } |
1193 if (types.size() == 1) { | 1269 } |
1194 TypeData singleType = types.iterator().next(); | 1270 |
1195 ExecutableTypeData executable = child.findExecutableType(singleType); | 1271 private void initializeUninitialized(final NodeData node) { |
1196 if (executable != null && (signatureIndex == 0 || !executable.hasUnexpectedValue(context))) { | |
1197 genericType = singleType; | |
1198 } | |
1199 } | |
1200 if (genericType == null) { | |
1201 ExecutableTypeData type = child.findAnyGenericExecutableType(context); | |
1202 if (type == null) { | |
1203 throw new AssertionError("No generic type not yet catched by parser."); | |
1204 } | |
1205 genericType = type.getType(); | |
1206 } | |
1207 return genericType.getPrimitiveType(); | |
1208 } | |
1209 } | |
1210 | |
1211 private static void initializeUninitialized(final NodeData node) { | |
1212 SpecializationData generic = node.getGenericSpecialization(); | 1272 SpecializationData generic = node.getGenericSpecialization(); |
1213 if (generic == null) { | 1273 if (generic == null) { |
1214 return; | 1274 return; |
1215 } | 1275 } |
1216 for (Parameter parameter : generic.getReturnTypeAndParameters()) { | 1276 for (Parameter parameter : generic.getReturnTypeAndParameters()) { |
1223 if (actualParameter != null) { | 1283 if (actualParameter != null) { |
1224 types.add(ElementUtils.getQualifiedName(actualParameter.getType())); | 1284 types.add(ElementUtils.getQualifiedName(actualParameter.getType())); |
1225 } | 1285 } |
1226 } | 1286 } |
1227 if (types.size() > 1) { | 1287 if (types.size() > 1) { |
1228 generic.replaceParameter(parameter.getLocalName(), new Parameter(parameter, node.getTypeSystem().getGenericTypeData())); | 1288 generic.replaceParameter(parameter.getLocalName(), new Parameter(parameter, context.getType(Object.class))); |
1229 } | 1289 } |
1230 } | 1290 } |
1231 TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", -1, node, generic.getSpecification(), null, null, generic.getReturnType(), generic.getParameters()); | 1291 TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", -1, node, generic.getSpecification(), null, null, generic.getReturnType(), generic.getParameters()); |
1232 // should not use messages from generic specialization | 1292 // should not use messages from generic specialization |
1233 uninializedMethod.getMessages().clear(); | 1293 uninializedMethod.getMessages().clear(); |
1239 return; | 1299 return; |
1240 } | 1300 } |
1241 | 1301 |
1242 SpecializationData generic = node.getGenericSpecialization(); | 1302 SpecializationData generic = node.getGenericSpecialization(); |
1243 | 1303 |
1244 List<TypeData> polymorphicSignature = new ArrayList<>(); | 1304 List<TypeMirror> polymorphicSignature = new ArrayList<>(); |
1245 List<Parameter> updatePolymorphic = Arrays.asList(); | 1305 List<Parameter> updatePolymorphic = Arrays.asList(); |
1246 for (Parameter genericParameter : updatePolymorphic) { | 1306 for (Parameter genericParameter : updatePolymorphic) { |
1247 if (!genericParameter.getSpecification().isSignature()) { | 1307 if (!genericParameter.getSpecification().isSignature()) { |
1248 continue; | 1308 continue; |
1249 } | 1309 } |
1250 | 1310 |
1251 Set<TypeData> usedTypes = new HashSet<>(); | 1311 Set<TypeMirror> usedTypes = new HashSet<>(); |
1252 for (SpecializationData specialization : node.getSpecializations()) { | 1312 for (SpecializationData specialization : node.getSpecializations()) { |
1253 if (!specialization.isSpecialized()) { | 1313 if (!specialization.isSpecialized()) { |
1254 continue; | 1314 continue; |
1255 } | 1315 } |
1256 Parameter parameter = specialization.findParameter(genericParameter.getLocalName()); | 1316 Parameter parameter = specialization.findParameter(genericParameter.getLocalName()); |
1257 if (parameter == null) { | 1317 if (parameter == null) { |
1258 throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName()); | 1318 throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName()); |
1259 } | 1319 } |
1260 usedTypes.add(parameter.getTypeSystemType()); | 1320 usedTypes.add(parameter.getType()); |
1261 } | 1321 } |
1262 | 1322 |
1263 TypeData polymorphicType; | 1323 TypeMirror polymorphicType; |
1264 if (usedTypes.size() == 1) { | 1324 if (usedTypes.size() == 1) { |
1265 polymorphicType = usedTypes.iterator().next(); | 1325 polymorphicType = usedTypes.iterator().next(); |
1266 } else { | 1326 } else { |
1267 polymorphicType = node.getTypeSystem().getGenericTypeData(); | 1327 polymorphicType = context.getType(Object.class); |
1268 } | 1328 } |
1269 polymorphicSignature.add(polymorphicType); | 1329 polymorphicSignature.add(polymorphicType); |
1270 } | 1330 } |
1271 | 1331 |
1272 SpecializationData polymorphic = new SpecializationData(node, generic, SpecializationKind.POLYMORPHIC); | 1332 SpecializationData polymorphic = new SpecializationData(node, generic, SpecializationKind.POLYMORPHIC); |
1368 continue; | 1428 continue; |
1369 } | 1429 } |
1370 ExecutableTypeData found = null; | 1430 ExecutableTypeData found = null; |
1371 List<ExecutableTypeData> executableElements = execution.getChild().findGenericExecutableTypes(context); | 1431 List<ExecutableTypeData> executableElements = execution.getChild().findGenericExecutableTypes(context); |
1372 for (ExecutableTypeData executable : executableElements) { | 1432 for (ExecutableTypeData executable : executableElements) { |
1373 if (executable.getType().equalsType(parameter.getTypeSystemType())) { | 1433 if (ElementUtils.typeEquals(executable.getReturnType(), parameter.getType())) { |
1374 found = executable; | 1434 found = executable; |
1375 break; | 1435 break; |
1376 } | 1436 } |
1377 } | 1437 } |
1378 if (found == null) { | 1438 if (found == null) { |
1427 return; | 1487 return; |
1428 } | 1488 } |
1429 | 1489 |
1430 List<Element> elements = new ArrayList<>(originalElements); | 1490 List<Element> elements = new ArrayList<>(originalElements); |
1431 Set<Element> unusedElements = new HashSet<>(elements); | 1491 Set<Element> unusedElements = new HashSet<>(elements); |
1432 for (TemplateMethod method : nodeData.getAllTemplateMethods()) { | 1492 for (ExecutableElement method : nodeData.getAllTemplateMethods()) { |
1433 unusedElements.remove(method.getMethod()); | 1493 unusedElements.remove(method); |
1434 } | 1494 } |
1435 | 1495 |
1436 for (NodeFieldData field : nodeData.getFields()) { | 1496 for (NodeFieldData field : nodeData.getFields()) { |
1437 if (field.getGetter() != null) { | 1497 if (field.getGetter() != null) { |
1438 unusedElements.remove(field.getGetter()); | 1498 unusedElements.remove(field.getGetter()); |