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());