Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java @ 12395:8e8347ecabbc
Truffle-DSL: implemented new polymorphic more compact generation strategy
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Fri, 11 Oct 2013 20:05:55 +0200 |
parents | 4e26955b6da2 |
children | c78612fb0120 |
comparison
equal
deleted
inserted
replaced
12394:df3af5e007ad | 12395:8e8347ecabbc |
---|---|
38 import com.oracle.truffle.dsl.processor.ast.*; | 38 import com.oracle.truffle.dsl.processor.ast.*; |
39 import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; | 39 import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; |
40 import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind; | 40 import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind; |
41 import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard; | 41 import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard; |
42 import com.oracle.truffle.dsl.processor.template.*; | 42 import com.oracle.truffle.dsl.processor.template.*; |
43 import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature; | |
44 import com.oracle.truffle.dsl.processor.typesystem.*; | 43 import com.oracle.truffle.dsl.processor.typesystem.*; |
45 | 44 |
46 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> { | 45 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> { |
47 | 46 |
48 private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; | 47 private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; |
49 | 48 |
50 private static final String EXECUTE_GENERIC_NAME = "executeGeneric0"; | 49 private static final String EXECUTE_GENERIC_NAME = "executeGeneric0"; |
51 private static final String EXECUTE_SPECIALIZE_NAME = "executeAndSpecialize0"; | 50 private static final String EXECUTE_SPECIALIZE_NAME = "executeAndSpecialize0"; |
52 | 51 |
52 private static final String UPDATE_TYPES_NAME = "updateTypes"; | |
53 | |
53 public NodeCodeGenerator(ProcessorContext context) { | 54 public NodeCodeGenerator(ProcessorContext context) { |
54 super(context); | 55 super(context); |
55 } | 56 } |
56 | 57 |
57 private TypeMirror getUnexpectedValueException() { | 58 private TypeMirror getUnexpectedValueException() { |
58 return getContext().getTruffleTypes().getUnexpectedValueException(); | 59 return getContext().getTruffleTypes().getUnexpectedValueException(); |
59 } | 60 } |
60 | 61 |
61 private static String factoryClassName(NodeData node) { | 62 private static String factoryClassName(NodeData node) { |
62 return node.getNodeId() + "Factory"; | 63 return node.getNodeId() + "Factory"; |
63 } | |
64 | |
65 private static String nodeCastClassName(NodeData node, TypeData type) { | |
66 String nodeid = resolveNodeId(node); | |
67 if (type == null) { | |
68 return nodeid + "ImplicitCast"; | |
69 } else { | |
70 return Utils.firstLetterUpperCase(Utils.getSimpleName(type.getPrimitiveType())) + "Cast"; | |
71 } | |
72 } | 64 } |
73 | 65 |
74 private static String nodeSpecializationClassName(SpecializationData specialization) { | 66 private static String nodeSpecializationClassName(SpecializationData specialization) { |
75 String nodeid = resolveNodeId(specialization.getNode()); | 67 String nodeid = resolveNodeId(specialization.getNode()); |
76 String name = Utils.firstLetterUpperCase(nodeid); | 68 String name = Utils.firstLetterUpperCase(nodeid); |
101 | 93 |
102 private static String valueNameEvaluated(ActualParameter targetParameter) { | 94 private static String valueNameEvaluated(ActualParameter targetParameter) { |
103 return valueName(targetParameter) + "Evaluated"; | 95 return valueName(targetParameter) + "Evaluated"; |
104 } | 96 } |
105 | 97 |
106 private static String typeName(ActualParameter param) { | 98 private static String implicitTypeName(ActualParameter param) { |
107 return param.getLocalName() + "Type"; | 99 return param.getLocalName() + "ImplicitType"; |
100 } | |
101 | |
102 private static String polymorphicTypeName(ActualParameter param) { | |
103 return param.getLocalName() + "PolymorphicType"; | |
108 } | 104 } |
109 | 105 |
110 private static String valueName(ActualParameter param) { | 106 private static String valueName(ActualParameter param) { |
111 return param.getLocalName(); | 107 return param.getLocalName(); |
112 } | 108 } |
297 builder.string("this."); | 293 builder.string("this."); |
298 } | 294 } |
299 builder.string(targetParameter.getSpecification().getName()); | 295 builder.string(targetParameter.getSpecification().getName()); |
300 builder.end(); | 296 builder.end(); |
301 } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) { | 297 } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) { |
302 builder.string("ex.getResult()"); | 298 builder.cast(targetParameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); |
303 } else if (!Utils.needsCastTo(getContext(), valueType, targetType)) { | 299 } else if (!Utils.needsCastTo(getContext(), valueType, targetType)) { |
304 builder.startGroup(); | 300 builder.startGroup(); |
305 builder.string(valueName(targetParameter)); | 301 builder.string(valueName(targetParameter)); |
306 builder.end(); | 302 builder.end(); |
307 } else { | 303 } else { |
319 String name = Utils.firstLetterUpperCase(nodeid); | 315 String name = Utils.firstLetterUpperCase(nodeid); |
320 name += "BaseNode"; | 316 name += "BaseNode"; |
321 return name; | 317 return name; |
322 } | 318 } |
323 | 319 |
324 private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, CodeTree value) { | 320 private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, CodeTree... args) { |
325 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 321 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
326 startCallTypeSystemMethod(context, builder, node, methodName); | 322 startCallTypeSystemMethod(context, builder, node.getTypeSystem(), methodName); |
327 builder.tree(value); | 323 for (CodeTree arg : args) { |
324 builder.tree(arg); | |
325 } | |
328 builder.end().end(); | 326 builder.end().end(); |
329 return builder.getRoot(); | 327 return builder.getRoot(); |
330 } | 328 } |
331 | 329 |
332 private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, NodeData node, String methodName) { | 330 private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, TypeSystemData typeSystem, String methodName) { |
333 VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, node.getTypeSystem()); | 331 VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, typeSystem); |
334 assert singleton != null; | 332 assert singleton != null; |
335 | 333 |
336 body.startGroup(); | 334 body.startGroup(); |
337 body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString()); | 335 body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString()); |
338 body.string(".").startCall(methodName); | 336 body.string(".").startCall(methodName); |
454 add(factory, node); | 452 add(factory, node); |
455 factory.getElement().getEnclosedElements().addAll(casts); | 453 factory.getElement().getEnclosedElements().addAll(casts); |
456 } | 454 } |
457 } | 455 } |
458 | 456 |
459 protected CodeTree createCastType(NodeData node, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) { | 457 protected CodeTree createCastType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) { |
460 if (targetType == null) { | 458 if (targetType == null) { |
461 return value; | 459 return value; |
462 } else if (sourceType != null && !sourceType.needsCastTo(getContext(), targetType)) { | 460 } else if (sourceType != null && !sourceType.needsCastTo(getContext(), targetType)) { |
463 return value; | 461 return value; |
464 } | 462 } |
468 if (expect) { | 466 if (expect) { |
469 targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType); | 467 targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType); |
470 } else { | 468 } else { |
471 targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); | 469 targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); |
472 } | 470 } |
473 startCallTypeSystemMethod(getContext(), builder, node, targetMethodName); | 471 startCallTypeSystemMethod(getContext(), builder, typeSystem, targetMethodName); |
474 builder.tree(value); | 472 builder.tree(value); |
475 builder.end().end(); | 473 builder.end().end(); |
476 return builder.getRoot(); | 474 return builder.getRoot(); |
475 } | |
476 | |
477 protected CodeTree createExpectType(TypeSystemData typeSystem, TypeData sourceType, TypeData targetType, CodeTree expression) { | |
478 return createCastType(typeSystem, sourceType, targetType, true, expression); | |
477 } | 479 } |
478 | 480 |
479 private class NodeFactoryFactory extends ClassElementFactory<NodeData> { | 481 private class NodeFactoryFactory extends ClassElementFactory<NodeData> { |
480 | 482 |
481 private final Map<NodeData, List<TypeElement>> childTypes; | 483 private final Map<NodeData, List<TypeElement>> childTypes; |
502 protected void createChildren(NodeData node) { | 504 protected void createChildren(NodeData node) { |
503 CodeTypeElement clazz = getElement(); | 505 CodeTypeElement clazz = getElement(); |
504 | 506 |
505 Modifier createVisibility = Utils.getVisibility(clazz.getModifiers()); | 507 Modifier createVisibility = Utils.getVisibility(clazz.getModifiers()); |
506 | 508 |
509 CodeTypeElement polymorphicNode = null; | |
507 if (node.needsFactory()) { | 510 if (node.needsFactory()) { |
508 NodeBaseFactory factory = new NodeBaseFactory(context); | 511 NodeBaseFactory factory = new NodeBaseFactory(context); |
509 add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization()); | 512 add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization()); |
510 generatedNode = factory.getElement(); | 513 generatedNode = factory.getElement(); |
511 | 514 |
514 } | 517 } |
515 | 518 |
516 createFactoryMethods(node, clazz, createVisibility); | 519 createFactoryMethods(node, clazz, createVisibility); |
517 | 520 |
518 if (node.isPolymorphic()) { | 521 if (node.isPolymorphic()) { |
519 PolymorphicNodeFactory generic = new PolymorphicNodeFactory(getContext(), generatedNode, true); | 522 PolymorphicNodeFactory generic = new PolymorphicNodeFactory(getContext(), generatedNode); |
520 add(generic, node.getGenericPolymorphicSpecialization()); | 523 add(generic, node.getGenericPolymorphicSpecialization()); |
521 | 524 polymorphicNode = generic.getElement(); |
522 for (SpecializationData specialization : node.getPolymorphicSpecializations()) { | |
523 if (specialization == node.getGenericPolymorphicSpecialization()) { | |
524 continue; | |
525 } | |
526 add(new PolymorphicNodeFactory(context, generic.getElement(), false), specialization); | |
527 } | |
528 } | 525 } |
529 for (SpecializationData specialization : node.getSpecializations()) { | 526 for (SpecializationData specialization : node.getSpecializations()) { |
530 if (!specialization.isReachable()) { | 527 if (!specialization.isReachable()) { |
531 continue; | 528 continue; |
532 } | 529 } |
542 clazz.add(createGetChildrenSignatureMethod(node)); | 539 clazz.add(createGetChildrenSignatureMethod(node)); |
543 clazz.add(createGetInstanceMethod(node, createVisibility)); | 540 clazz.add(createGetInstanceMethod(node, createVisibility)); |
544 clazz.add(createInstanceConstant(node, clazz.asType())); | 541 clazz.add(createInstanceConstant(node, clazz.asType())); |
545 } | 542 } |
546 | 543 |
544 if (polymorphicNode != null) { | |
545 patchParameterType(clazz, UPDATE_TYPES_NAME, generatedNode.asType(), polymorphicNode.asType()); | |
546 } | |
547 | |
547 for (NodeData childNode : childTypes.keySet()) { | 548 for (NodeData childNode : childTypes.keySet()) { |
548 if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { | 549 if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { |
549 continue; | 550 continue; |
550 } | 551 } |
551 | 552 |
566 List<NodeData> children = node.getNodeDeclaringChildren(); | 567 List<NodeData> children = node.getNodeDeclaringChildren(); |
567 if (node.getParent() == null && children.size() > 0) { | 568 if (node.getParent() == null && children.size() > 0) { |
568 clazz.add(createGetFactories(node)); | 569 clazz.add(createGetFactories(node)); |
569 } | 570 } |
570 | 571 |
572 } | |
573 | |
574 private void patchParameterType(CodeTypeElement enclosingClass, String methodName, TypeMirror originalType, TypeMirror newType) { | |
575 for (TypeElement enclosedType : ElementFilter.typesIn(enclosingClass.getEnclosedElements())) { | |
576 CodeTypeElement type = (CodeTypeElement) enclosedType; | |
577 ExecutableElement method = type.getMethod(methodName); | |
578 for (VariableElement v : method.getParameters()) { | |
579 CodeVariableElement var = (CodeVariableElement) v; | |
580 if (Utils.typeEquals(var.getType(), originalType)) { | |
581 var.setType(newType); | |
582 } | |
583 } | |
584 } | |
571 } | 585 } |
572 | 586 |
573 private CodeExecutableElement createGetNodeClassMethod(NodeData node) { | 587 private CodeExecutableElement createGetNodeClassMethod(NodeData node) { |
574 TypeMirror returnType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType()); | 588 TypeMirror returnType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType()); |
575 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass"); | 589 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass"); |
939 setter.getParameters().add(new CodeVariableElement(clazz.asType(), "next0")); | 953 setter.getParameters().add(new CodeVariableElement(clazz.asType(), "next0")); |
940 CodeTreeBuilder builder = setter.createBuilder(); | 954 CodeTreeBuilder builder = setter.createBuilder(); |
941 builder.statement("this.next0 = adoptChild(next0)"); | 955 builder.statement("this.next0 = adoptChild(next0)"); |
942 clazz.add(setter); | 956 clazz.add(setter); |
943 | 957 |
944 createIsCompatible(clazz, null); | 958 CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getGenericPolymorphicSpecialization()); |
945 | |
946 CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getGenericPolymorphicSpecialization(), null); | |
947 clazz.add(genericCachedExecute); | 959 clazz.add(genericCachedExecute); |
948 for (SpecializationData polymorph : node.getPolymorphicSpecializations()) { | 960 |
949 if (polymorph == node.getGenericPolymorphicSpecialization()) { | 961 getElement().add(createUpdateTypes(clazz.asType())); |
950 continue; | |
951 } | |
952 clazz.add(createCachedExecute(node, polymorph, genericCachedExecute)); | |
953 } | |
954 } | 962 } |
955 | 963 |
956 for (CodeExecutableElement method : createImplicitChildrenAccessors()) { | 964 for (CodeExecutableElement method : createImplicitChildrenAccessors()) { |
957 clazz.add(method); | 965 clazz.add(method); |
958 } | 966 } |
966 } | 974 } |
967 } | 975 } |
968 | 976 |
969 private List<CodeExecutableElement> createImplicitChildrenAccessors() { | 977 private List<CodeExecutableElement> createImplicitChildrenAccessors() { |
970 NodeData node = getModel().getNode(); | 978 NodeData node = getModel().getNode(); |
971 List<CodeExecutableElement> methods = new ArrayList<>(); | 979 // Map<NodeChildData, Set<TypeData>> expectTypes = new HashMap<>(); |
972 Map<NodeChildData, Set<TypeData>> expectTypes = new HashMap<>(); | 980 @SuppressWarnings("unchecked") |
981 List<Set<TypeData>> expectTypes = Arrays.<Set<TypeData>> asList(new Set[node.getGenericSpecialization().getParameters().size()]); | |
982 | |
973 for (ExecutableTypeData executableType : node.getExecutableTypes()) { | 983 for (ExecutableTypeData executableType : node.getExecutableTypes()) { |
974 for (int i = 0; i < executableType.getEvaluatedCount(); i++) { | 984 for (int i = 0; i < executableType.getEvaluatedCount(); i++) { |
975 ActualParameter parameter = executableType.getSignatureParameter(i); | 985 ActualParameter parameter = executableType.getSignatureParameter(i); |
976 NodeChildData child = node.findChild(parameter.getSpecification().getName()); | 986 if (i >= expectTypes.size()) { |
977 Set<TypeData> types = expectTypes.get(child); | 987 break; |
988 } | |
989 Set<TypeData> types = expectTypes.get(i); | |
978 if (types == null) { | 990 if (types == null) { |
979 types = new TreeSet<>(); | 991 types = new TreeSet<>(); |
980 expectTypes.put(child, types); | 992 expectTypes.set(i, types); |
981 } | 993 } |
982 types.add(parameter.getTypeSystemType()); | 994 types.add(parameter.getTypeSystemType()); |
983 } | 995 } |
984 } | 996 } |
985 | 997 |
986 Map<NodeChildData, Set<TypeData>> visitedMap = new HashMap<>(); | 998 List<CodeExecutableElement> methods = new ArrayList<>(); |
999 @SuppressWarnings("unchecked") | |
1000 List<Set<TypeData>> visitedList = Arrays.<Set<TypeData>> asList(new Set[node.getGenericSpecialization().getParameters().size()]); | |
987 for (SpecializationData spec : node.getSpecializations()) { | 1001 for (SpecializationData spec : node.getSpecializations()) { |
1002 int signatureIndex = -1; | |
988 for (ActualParameter param : spec.getParameters()) { | 1003 for (ActualParameter param : spec.getParameters()) { |
989 if (!param.getSpecification().isSignature()) { | 1004 if (!param.getSpecification().isSignature()) { |
990 continue; | 1005 continue; |
991 } | 1006 } |
992 NodeChildData child = node.findChild(param.getSpecification().getName()); | 1007 signatureIndex++; |
993 Set<TypeData> visitedTypeData = visitedMap.get(child); | 1008 Set<TypeData> visitedTypeData = visitedList.get(signatureIndex); |
994 if (visitedTypeData == null) { | 1009 if (visitedTypeData == null) { |
995 visitedTypeData = new TreeSet<>(); | 1010 visitedTypeData = new TreeSet<>(); |
996 visitedMap.put(child, visitedTypeData); | 1011 visitedList.set(signatureIndex, visitedTypeData); |
997 } | 1012 } |
1013 | |
998 if (visitedTypeData.contains(param.getTypeSystemType())) { | 1014 if (visitedTypeData.contains(param.getTypeSystemType())) { |
999 continue; | 1015 continue; |
1000 } | 1016 } |
1001 visitedTypeData.add(param.getTypeSystemType()); | 1017 visitedTypeData.add(param.getTypeSystemType()); |
1002 | 1018 |
1003 Set<TypeData> expect = expectTypes.get(child); | 1019 Set<TypeData> expect = expectTypes.get(signatureIndex); |
1004 if (expect == null) { | 1020 if (expect == null) { |
1005 expect = Collections.emptySet(); | 1021 expect = Collections.emptySet(); |
1006 } | 1022 } |
1007 | 1023 |
1008 methods.addAll(createExecuteChilds(param, expect)); | 1024 methods.addAll(createExecuteChilds(param, expect)); |
1075 builder.end(); | 1091 builder.end(); |
1076 | 1092 |
1077 return method; | 1093 return method; |
1078 } | 1094 } |
1079 | 1095 |
1080 protected void createIsCompatible(CodeTypeElement clazz, SpecializationData specialization) { | 1096 private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) { |
1081 CodeExecutableElement isCompatible = new CodeExecutableElement(modifiers(PROTECTED), context.getType(boolean.class), "isCompatible0"); | |
1082 isCompatible.addParameter(new CodeVariableElement(getContext().getType(Class.class), "type")); | |
1083 | |
1084 if (specialization == null) { | |
1085 isCompatible.getModifiers().add(ABSTRACT); | |
1086 } else if (specialization.isGeneric()) { | |
1087 isCompatible.createBuilder().startThrow().startNew(getContext().getType(AssertionError.class)).end().end(); | |
1088 } else if (specialization.isPolymorphic()) { | |
1089 isCompatible.createBuilder().startReturn().string("type != getClass() && next0.isCompatible0(type)").end(); | |
1090 } else if (specialization.isUninitialized()) { | |
1091 isCompatible.createBuilder().returnTrue(); | |
1092 } else { | |
1093 NodeData node = specialization.getNode(); | |
1094 CodeTreeBuilder builder = isCompatible.createBuilder(); | |
1095 | |
1096 Signature specializationSignature = specialization.getSignature(); | |
1097 List<SpecializationData> compatible = new ArrayList<>(); | |
1098 for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) { | |
1099 if (specializationSignature.isCompatibleTo(polymorphic.getSignature())) { | |
1100 compatible.add(polymorphic); | |
1101 } | |
1102 } | |
1103 | |
1104 if (compatible.isEmpty()) { | |
1105 builder.returnFalse(); | |
1106 } else { | |
1107 builder.startIf(); | |
1108 String and = ""; | |
1109 for (SpecializationData polymorphic : compatible) { | |
1110 builder.string(and); | |
1111 builder.string("type == ").string(nodePolymorphicClassName(node, polymorphic)).string(".class"); | |
1112 and = " || "; | |
1113 } | |
1114 builder.end().startBlock(); | |
1115 builder.startReturn().startCall("next0", "isCompatible0").string("type").end().end(); | |
1116 builder.end(); | |
1117 builder.returnFalse(); | |
1118 } | |
1119 } | |
1120 | |
1121 clazz.add(isCompatible); | |
1122 } | |
1123 | |
1124 private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph, CodeExecutableElement genericPolymorphMethod) { | |
1125 String name = executeCachedName(polymorph); | 1097 String name = executeCachedName(polymorph); |
1126 CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED), polymorph.getReturnType().getType(), name); | 1098 CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), name); |
1099 addInternalValueParameters(cachedExecute, polymorph, true, true); | |
1127 | 1100 |
1128 ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0); | 1101 ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0); |
1129 boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext()); | 1102 boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext()); |
1130 if (sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) { | 1103 if (sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) { |
1131 sourceThrowsUnexpected = false; | 1104 sourceThrowsUnexpected = false; |
1132 } | 1105 } |
1133 if (sourceThrowsUnexpected) { | 1106 if (sourceThrowsUnexpected) { |
1134 cachedExecute.getThrownTypes().add(getContext().getType(UnexpectedResultException.class)); | 1107 cachedExecute.getThrownTypes().add(getContext().getType(UnexpectedResultException.class)); |
1135 } | 1108 } |
1136 addInternalValueParameters(cachedExecute, polymorph, true, true); | |
1137 | |
1138 if (polymorph == node.getGenericPolymorphicSpecialization()) { | |
1139 cachedExecute.getModifiers().add(ABSTRACT); | |
1140 } else { | |
1141 SpecializationData genericPolymorph = node.getGenericPolymorphicSpecialization(); | |
1142 CodeTreeBuilder builder = cachedExecute.createBuilder(); | |
1143 ExecutableTypeData genericExecutable = new ExecutableTypeData(genericPolymorph, genericPolymorphMethod, node.getTypeSystem(), genericPolymorph.getReturnType().getTypeSystemType()); | |
1144 ExecutableTypeData specificExecutable = new ExecutableTypeData(polymorph, cachedExecute, node.getTypeSystem(), polymorph.getReturnType().getTypeSystemType()); | |
1145 builder.tree(createCastingExecute(builder, polymorph, specificExecutable, genericExecutable)); | |
1146 } | |
1147 | |
1148 return cachedExecute; | 1109 return cachedExecute; |
1149 | 1110 |
1150 } | 1111 } |
1151 | 1112 |
1152 private void createConstructors(NodeData node, CodeTypeElement clazz) { | 1113 private void createConstructors(NodeData node, CodeTypeElement clazz) { |
1318 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), rootGroup, true, new CodeBlock<SpecializationData>() { | 1279 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), rootGroup, true, new CodeBlock<SpecializationData>() { |
1319 | 1280 |
1320 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { | 1281 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { |
1321 return createGenericInvokeAndSpecialize(b, node.getGenericSpecialization(), current, currentNodeVar); | 1282 return createGenericInvokeAndSpecialize(b, node.getGenericSpecialization(), current, currentNodeVar); |
1322 } | 1283 } |
1323 }, null, false, true)); | 1284 }, null, false, true, false)); |
1324 | 1285 |
1325 boolean firstUnreachable = true; | 1286 boolean firstUnreachable = true; |
1326 for (SpecializationData current : node.getSpecializations()) { | 1287 for (SpecializationData current : node.getSpecializations()) { |
1327 if (current.isUninitialized() || current.isReachable()) { | 1288 if (current.isUninitialized() || current.isReachable()) { |
1328 continue; | 1289 continue; |
1362 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, false, new CodeBlock<SpecializationData>() { | 1323 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, false, new CodeBlock<SpecializationData>() { |
1363 | 1324 |
1364 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { | 1325 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { |
1365 return createGenericInvoke(builder, current.getNode().getGenericSpecialization(), current); | 1326 return createGenericInvoke(builder, current.getNode().getGenericSpecialization(), current); |
1366 } | 1327 } |
1367 }, null, false, true)); | 1328 }, null, false, true, false)); |
1368 | 1329 |
1369 emitUnreachableSpecializations(builder, node); | 1330 emitUnreachableSpecializations(builder, node); |
1370 | 1331 |
1371 return method; | 1332 return method; |
1372 } | 1333 } |
1379 builder.string("// unreachable ").string(current.getId()).newLine(); | 1340 builder.string("// unreachable ").string(current.getId()).newLine(); |
1380 } | 1341 } |
1381 } | 1342 } |
1382 | 1343 |
1383 protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final boolean checkMinimumState, | 1344 protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final boolean checkMinimumState, |
1384 final CodeBlock<SpecializationData> guardedblock, final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions) { | 1345 final CodeBlock<SpecializationData> guardedblock, final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions, final boolean typedCasts) { |
1385 return guard(outerParent, source, group, checkMinimumState, new CodeBlock<Integer>() { | 1346 return guard(outerParent, source, group, checkMinimumState, new CodeBlock<Integer>() { |
1386 | 1347 |
1387 public CodeTree create(CodeTreeBuilder parent, Integer ifCount) { | 1348 public CodeTree create(CodeTreeBuilder parent, Integer ifCount) { |
1388 CodeTreeBuilder builder = parent.create(); | 1349 CodeTreeBuilder builder = parent.create(); |
1389 | 1350 |
1392 | 1353 |
1393 assert group.getChildren().isEmpty() : "missed a specialization"; | 1354 assert group.getChildren().isEmpty() : "missed a specialization"; |
1394 | 1355 |
1395 } else { | 1356 } else { |
1396 for (SpecializationGroup childGroup : group.getChildren()) { | 1357 for (SpecializationGroup childGroup : group.getChildren()) { |
1397 builder.tree(createExecuteTree(builder, source, childGroup, checkMinimumState, guardedblock, null, false, emitAssumptions)); | 1358 builder.tree(createExecuteTree(builder, source, childGroup, checkMinimumState, guardedblock, null, false, emitAssumptions, typedCasts)); |
1398 } | 1359 } |
1399 } | 1360 } |
1400 | 1361 |
1401 return builder.getRoot(); | 1362 return builder.getRoot(); |
1402 } | 1363 } |
1403 }, elseBlock, forceElse, emitAssumptions); | 1364 }, elseBlock, forceElse, emitAssumptions, typedCasts); |
1404 } | 1365 } |
1405 | 1366 |
1406 private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, CodeBlock<Integer> bodyBlock, CodeTree elseBlock, | 1367 private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, CodeBlock<Integer> bodyBlock, CodeTree elseBlock, |
1407 boolean forceElse, boolean emitAssumptions) { | 1368 boolean forceElse, boolean emitAssumptions, boolean typedCasts) { |
1408 CodeTreeBuilder builder = parent.create(); | 1369 CodeTreeBuilder builder = parent.create(); |
1409 | 1370 |
1410 int ifCount = emitGuards(builder, source, group, checkMinimumState, emitAssumptions); | 1371 int ifCount = emitGuards(builder, source, group, checkMinimumState, emitAssumptions, typedCasts); |
1411 | 1372 |
1412 if (isReachableGroup(group, ifCount, checkMinimumState)) { | 1373 if (isReachableGroup(group, ifCount, checkMinimumState)) { |
1413 builder.tree(bodyBlock.create(builder, ifCount)); | 1374 builder.tree(bodyBlock.create(builder, ifCount)); |
1414 } | 1375 } |
1415 | 1376 |
1443 } | 1404 } |
1444 | 1405 |
1445 return true; | 1406 return true; |
1446 } | 1407 } |
1447 | 1408 |
1448 private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, boolean emitAssumptions) { | 1409 private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean checkMinimumState, boolean emitAssumptions, boolean typedCasts) { |
1449 NodeData node = source.getNode(); | 1410 NodeData node = source.getNode(); |
1450 | 1411 |
1451 CodeTreeBuilder guardsBuilder = builder.create(); | 1412 CodeTreeBuilder guardsBuilder = builder.create(); |
1452 CodeTreeBuilder castBuilder = builder.create(); | 1413 CodeTreeBuilder castBuilder = builder.create(); |
1453 CodeTreeBuilder guardsCastBuilder = builder.create(); | 1414 CodeTreeBuilder guardsCastBuilder = builder.create(); |
1513 NodeChildData child = node.findChild(valueParam.getSpecification().getName()); | 1474 NodeChildData child = node.findChild(valueParam.getSpecification().getName()); |
1514 if (child == null) { | 1475 if (child == null) { |
1515 throw new IllegalStateException(); | 1476 throw new IllegalStateException(); |
1516 } | 1477 } |
1517 | 1478 |
1518 CodeTree implicitGuard = createTypeGuard(guardsBuilder, child, valueParam, typeGuard.getType()); | 1479 CodeTree implicitGuard = createTypeGuard(guardsBuilder, child, valueParam, typeGuard.getType(), typedCasts); |
1519 if (implicitGuard != null) { | 1480 if (implicitGuard != null) { |
1520 guardsBuilder.string(guardsAnd); | 1481 guardsBuilder.string(guardsAnd); |
1521 guardsBuilder.tree(implicitGuard); | 1482 guardsBuilder.tree(implicitGuard); |
1522 guardsAnd = " && "; | 1483 guardsAnd = " && "; |
1523 } | 1484 } |
1524 | 1485 |
1525 CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType(), checkMinimumState); | 1486 CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType(), checkMinimumState, typedCasts); |
1526 if (cast != null) { | 1487 if (cast != null) { |
1527 castBuilder.tree(cast); | 1488 castBuilder.tree(cast); |
1528 } | 1489 } |
1529 } | 1490 } |
1530 | 1491 |
1591 signatureIndex++; | 1552 signatureIndex++; |
1592 } | 1553 } |
1593 return false; | 1554 return false; |
1594 } | 1555 } |
1595 | 1556 |
1596 private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType) { | 1557 private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean typedCasts) { |
1597 NodeData node = field.getNodeData(); | 1558 NodeData node = field.getNodeData(); |
1598 | 1559 |
1599 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 1560 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
1600 | 1561 |
1601 TypeData sourceType = source.getTypeSystemType(); | 1562 TypeData sourceType = source.getTypeSystemType(); |
1613 builder.string("!").string(valueName(shortCircuit)); | 1574 builder.string("!").string(valueName(shortCircuit)); |
1614 builder.string(" || "); | 1575 builder.string(" || "); |
1615 } | 1576 } |
1616 | 1577 |
1617 String castMethodName; | 1578 String castMethodName; |
1579 String castTypeName = null; | |
1618 List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); | 1580 List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); |
1619 if (types.size() > 1) { | 1581 if (types.size() > 1) { |
1620 castMethodName = TypeSystemCodeGenerator.isImplicitTypeMethodName(targetType); | 1582 castMethodName = TypeSystemCodeGenerator.isImplicitTypeMethodName(targetType); |
1583 if (typedCasts) { | |
1584 castTypeName = implicitTypeName(source); | |
1585 } | |
1621 } else { | 1586 } else { |
1622 castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType); | 1587 castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType); |
1623 } | 1588 } |
1624 | 1589 |
1625 startCallTypeSystemMethod(getContext(), builder, node, castMethodName); | 1590 startCallTypeSystemMethod(getContext(), builder, node.getTypeSystem(), castMethodName); |
1626 builder.string(valueName(source)); | 1591 builder.string(valueName(source)); |
1592 if (castTypeName != null) { | |
1593 builder.string(castTypeName); | |
1594 } | |
1627 builder.end().end(); // call | 1595 builder.end().end(); // call |
1628 | 1596 |
1629 if (field.isShortCircuit()) { | 1597 if (field.isShortCircuit()) { |
1630 builder.string(")"); | 1598 builder.string(")"); |
1631 } | 1599 } |
1633 builder.end(); // group | 1601 builder.end(); // group |
1634 | 1602 |
1635 return builder.getRoot(); | 1603 return builder.getRoot(); |
1636 } | 1604 } |
1637 | 1605 |
1638 private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean checkMinimumState) { | 1606 // TODO merge redundancies with #createTypeGuard |
1607 private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean checkMinimumState, boolean typedCasts) { | |
1639 NodeData node = field.getNodeData(); | 1608 NodeData node = field.getNodeData(); |
1640 TypeData sourceType = source.getTypeSystemType(); | 1609 TypeData sourceType = source.getTypeSystemType(); |
1641 | 1610 |
1642 if (!sourceType.needsCastTo(getContext(), targetType)) { | 1611 if (!sourceType.needsCastTo(getContext(), targetType)) { |
1643 return null; | 1612 return null; |
1649 assert shortCircuit != null; | 1618 assert shortCircuit != null; |
1650 condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); | 1619 condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); |
1651 } | 1620 } |
1652 | 1621 |
1653 String castMethodName; | 1622 String castMethodName; |
1623 String castTypeName = null; | |
1654 List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); | 1624 List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); |
1655 if (types.size() > 1) { | 1625 if (types.size() > 1) { |
1656 castMethodName = TypeSystemCodeGenerator.asImplicitTypeMethodName(targetType); | 1626 castMethodName = TypeSystemCodeGenerator.asImplicitTypeMethodName(targetType); |
1627 if (typedCasts) { | |
1628 castTypeName = implicitTypeName(source); | |
1629 } | |
1657 } else { | 1630 } else { |
1658 castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); | 1631 castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); |
1659 } | 1632 } |
1660 | 1633 |
1661 CodeTree value = createCallTypeSystemMethod(context, parent, node, castMethodName, CodeTreeBuilder.singleString(valueName(source))); | 1634 List<CodeTree> args = new ArrayList<>(); |
1635 args.add(CodeTreeBuilder.singleString(valueName(source))); | |
1636 if (castTypeName != null) { | |
1637 args.add(CodeTreeBuilder.singleString(castTypeName)); | |
1638 } | |
1639 | |
1640 CodeTree value = createCallTypeSystemMethod(context, parent, node, castMethodName, args.toArray(new CodeTree[0])); | |
1662 | 1641 |
1663 CodeTreeBuilder builder = parent.create(); | 1642 CodeTreeBuilder builder = parent.create(); |
1664 builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, value)); | 1643 builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, value)); |
1665 if (checkMinimumState && types.size() > 1) { | 1644 if (checkMinimumState && types.size() > 1) { |
1666 CodeTree castType = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.getImplicitClass(targetType), CodeTreeBuilder.singleString(valueName(source))); | 1645 CodeTree castType = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.getImplicitClass(targetType), CodeTreeBuilder.singleString(valueName(source))); |
1667 builder.tree(createLazyAssignment(builder, typeName(source), getContext().getType(Class.class), condition, castType)); | 1646 builder.tree(createLazyAssignment(builder, implicitTypeName(source), getContext().getType(Class.class), condition, castType)); |
1668 } | 1647 } |
1669 | 1648 |
1670 return builder.getRoot(); | 1649 return builder.getRoot(); |
1671 } | 1650 } |
1672 | 1651 |
1812 continue; | 1791 continue; |
1813 } | 1792 } |
1814 NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); | 1793 NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); |
1815 List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); | 1794 List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); |
1816 if (types.size() > 1) { | 1795 if (types.size() > 1) { |
1817 replaceCall.string(typeName(param)); | 1796 replaceCall.string(implicitTypeName(param)); |
1818 } | 1797 } |
1819 } | 1798 } |
1820 replaceCall.end().end(); | 1799 replaceCall.end().end(); |
1821 | 1800 |
1822 if (message == null) { | 1801 if (message == null) { |
1944 return builder.getRoot(); | 1923 return builder.getRoot(); |
1945 } | 1924 } |
1946 | 1925 |
1947 protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, ExecutableTypeData castedType, CodeTree value) { | 1926 protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, ExecutableTypeData castedType, CodeTree value) { |
1948 boolean hasUnexpected = castedType.hasUnexpectedValue(getContext()); | 1927 boolean hasUnexpected = castedType.hasUnexpectedValue(getContext()); |
1949 return createCastType(node, sourceType, castedType.getType(), hasUnexpected, value); | 1928 return createCastType(node.getTypeSystem(), sourceType, castedType.getType(), hasUnexpected, value); |
1950 } | 1929 } |
1951 | 1930 |
1952 protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters, | 1931 protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters, |
1953 ActualParameter unexpectedParameter) { | 1932 ActualParameter unexpectedParameter) { |
1954 CodeTreeBuilder builder = parent.create(); | 1933 CodeTreeBuilder builder = parent.create(); |
1956 for (ActualParameter targetParameter : targetParameters) { | 1935 for (ActualParameter targetParameter : targetParameters) { |
1957 NodeChildData child = node.findChild(targetParameter.getSpecification().getName()); | 1936 NodeChildData child = node.findChild(targetParameter.getSpecification().getName()); |
1958 if (!targetParameter.getSpecification().isSignature()) { | 1937 if (!targetParameter.getSpecification().isSignature()) { |
1959 continue; | 1938 continue; |
1960 } | 1939 } |
1961 TypeData targetType = targetParameter.getTypeSystemType(); | 1940 CodeTree executionExpressions = createExecuteChild(builder, child, sourceExecutable, targetParameter, unexpectedParameter); |
1962 ExecutableTypeData targetExecutable = null; | 1941 CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, specialization, sourceExecutable, targetParameter, isShortCircuit(child), unexpectedParameter); |
1963 if (child != null) { | 1942 CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, specialization, targetParameter, unexpectedParameter); |
1964 targetExecutable = child.findExecutableType(getContext(), targetType); | |
1965 } | |
1966 | |
1967 if (targetExecutable == null) { | |
1968 // TODO what to do? assertion? | |
1969 continue; | |
1970 } | |
1971 | |
1972 CodeTree executionExpressions = createExecutionExpresssions(builder, child, sourceExecutable, targetExecutable, targetParameter, unexpectedParameter); | |
1973 | |
1974 String targetVarName = valueName(targetParameter); | |
1975 CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, targetVarName, specialization, sourceExecutable, targetExecutable, targetParameter, | |
1976 isShortCircuit(child)); | |
1977 CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, targetVarName, specialization, targetParameter, unexpectedParameter); | |
1978 | 1943 |
1979 if (shortCircuitTree == executionExpressions) { | 1944 if (shortCircuitTree == executionExpressions) { |
1980 if (containsNewLine(executionExpressions)) { | 1945 if (containsNewLine(executionExpressions)) { |
1981 builder.declaration(sourceExecutable.getType().getPrimitiveType(), targetVarName); | 1946 builder.declaration(targetParameter.getType(), valueName(targetParameter)); |
1982 builder.tree(shortCircuitTree); | 1947 builder.tree(shortCircuitTree); |
1983 } else { | 1948 } else { |
1984 builder.startStatement().type(targetParameter.getType()).string(" ").tree(shortCircuitTree).end(); | 1949 builder.startStatement().type(targetParameter.getType()).string(" ").tree(shortCircuitTree).end(); |
1985 } | 1950 } |
1986 } else { | 1951 } else { |
1989 | 1954 |
1990 } | 1955 } |
1991 return builder.getRoot(); | 1956 return builder.getRoot(); |
1992 } | 1957 } |
1993 | 1958 |
1994 private CodeTree createExecutionExpresssions(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ExecutableTypeData targetExecutable, ActualParameter param, | 1959 private ExecutableTypeData resolveExecutableType(NodeChildData child, TypeData type) { |
1995 ActualParameter unexpectedParameter) { | 1960 ExecutableTypeData targetExecutable = child.findExecutableType(getContext(), type); |
1961 if (targetExecutable == null) { | |
1962 targetExecutable = child.findAnyGenericExecutableType(getContext()); | |
1963 } | |
1964 return targetExecutable; | |
1965 } | |
1966 | |
1967 private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ActualParameter targetParameter, ActualParameter unexpectedParameter) { | |
1968 SpecializationData specialization = getModel(); | |
1969 if (specialization.isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) { | |
1970 TreeSet<TypeData> possiblePolymorphicTypes = lookupPolymorphicTargetTypes(targetParameter); | |
1971 | |
1972 CodeTreeBuilder builder = parent.create(); | |
1973 | |
1974 boolean elseIf = false; | |
1975 for (TypeData possiblePolymoprhicType : possiblePolymorphicTypes) { | |
1976 if (possiblePolymoprhicType.isGeneric()) { | |
1977 continue; | |
1978 } | |
1979 elseIf = builder.startIf(elseIf); | |
1980 | |
1981 ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); | |
1982 TypeData sourceType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; | |
1983 builder.string(polymorphicTypeName(targetParameter)).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType()); | |
1984 builder.end().startBlock(); | |
1985 builder.startStatement(); | |
1986 builder.tree(createExecuteChildExpression(parent, child, sourceType, new ActualParameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null)); | |
1987 builder.end(); | |
1988 builder.end(); | |
1989 } | |
1990 | |
1991 builder.startElseBlock(); | |
1992 builder.startStatement().tree(createExecuteChildImplicit(parent, child, sourceExecutable, targetParameter, unexpectedParameter)).end(); | |
1993 builder.end(); | |
1994 | |
1995 return builder.getRoot(); | |
1996 } else { | |
1997 return createExecuteChildImplicit(parent, child, sourceExecutable, targetParameter, unexpectedParameter); | |
1998 } | |
1999 } | |
2000 | |
2001 protected final TreeSet<TypeData> lookupPolymorphicTargetTypes(ActualParameter param) { | |
2002 SpecializationData specialization = getModel(); | |
2003 TreeSet<TypeData> possiblePolymorphicTypes = new TreeSet<>(); | |
2004 for (SpecializationData otherSpecialization : specialization.getNode().getSpecializations()) { | |
2005 if (!otherSpecialization.isSpecialized()) { | |
2006 continue; | |
2007 } | |
2008 ActualParameter otherParameter = otherSpecialization.findParameter(param.getLocalName()); | |
2009 if (otherParameter != null) { | |
2010 possiblePolymorphicTypes.add(otherParameter.getTypeSystemType()); | |
2011 } | |
2012 } | |
2013 return possiblePolymorphicTypes; | |
2014 } | |
2015 | |
2016 private CodeTree createExecuteChildImplicit(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ActualParameter param, ActualParameter unexpectedParameter) { | |
1996 CodeTreeBuilder builder = parent.create(); | 2017 CodeTreeBuilder builder = parent.create(); |
1997 | |
1998 ActualParameter sourceParameter = sourceExecutable.findParameter(param.getLocalName()); | 2018 ActualParameter sourceParameter = sourceExecutable.findParameter(param.getLocalName()); |
1999 | |
2000 String childExecuteName = createExecuteChildMethodName(param, sourceParameter != null); | 2019 String childExecuteName = createExecuteChildMethodName(param, sourceParameter != null); |
2001 if (childExecuteName != null) { | 2020 if (childExecuteName != null) { |
2002 builder.string(valueName(param)); | 2021 builder.string(valueName(param)); |
2003 builder.string(" = "); | 2022 builder.string(" = "); |
2004 builder.startCall(childExecuteName); | 2023 builder.startCall(childExecuteName); |
2012 | 2031 |
2013 if (sourceParameter != null) { | 2032 if (sourceParameter != null) { |
2014 builder.string(valueNameEvaluated(sourceParameter)); | 2033 builder.string(valueNameEvaluated(sourceParameter)); |
2015 } | 2034 } |
2016 | 2035 |
2017 builder.string(typeName(param)); | 2036 builder.string(implicitTypeName(param)); |
2018 | 2037 |
2019 builder.end(); | 2038 builder.end(); |
2020 } else { | 2039 } else { |
2021 List<TypeData> sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); | 2040 List<TypeData> sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); |
2022 TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; | 2041 TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; |
2023 if (sourceTypes.size() > 1) { | 2042 if (sourceTypes.size() > 1) { |
2024 builder.tree(createExecuteExpressions(parent, param, expectType)); | 2043 builder.tree(createExecuteChildImplicitExpressions(parent, param, expectType)); |
2025 } else { | 2044 } else { |
2026 builder.tree(createExecuteExpression(parent, child, expectType, targetExecutable, param, unexpectedParameter, null)); | 2045 builder.tree(createExecuteChildExpression(parent, child, expectType, param, unexpectedParameter, null)); |
2027 } | 2046 } |
2028 } | 2047 } |
2029 return builder.getRoot(); | 2048 return builder.getRoot(); |
2030 } | 2049 } |
2031 | 2050 |
2069 method.getThrownTypes().add(getContext().getTruffleTypes().getUnexpectedValueException()); | 2088 method.getThrownTypes().add(getContext().getTruffleTypes().getUnexpectedValueException()); |
2070 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); | 2089 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); |
2071 if (expectType != null) { | 2090 if (expectType != null) { |
2072 method.addParameter(new CodeVariableElement(expectType.getPrimitiveType(), valueNameEvaluated(param))); | 2091 method.addParameter(new CodeVariableElement(expectType.getPrimitiveType(), valueNameEvaluated(param))); |
2073 } | 2092 } |
2074 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), typeName(param))); | 2093 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param))); |
2075 | 2094 |
2076 CodeTreeBuilder builder = method.createBuilder(); | 2095 CodeTreeBuilder builder = method.createBuilder(); |
2077 builder.declaration(param.getType(), valueName(param)); | 2096 builder.declaration(param.getType(), valueName(param)); |
2078 builder.tree(createExecuteExpressions(builder, param, expectType)); | 2097 builder.tree(createExecuteChildImplicitExpressions(builder, param, expectType)); |
2079 builder.startReturn().string(valueName(param)).end(); | 2098 builder.startReturn().string(valueName(param)).end(); |
2080 | 2099 |
2081 return method; | 2100 return method; |
2082 } | 2101 } |
2083 | 2102 |
2084 private CodeTree createExecuteExpressions(CodeTreeBuilder parent, ActualParameter param, TypeData expectType) { | 2103 private CodeTree createExecuteChildImplicitExpressions(CodeTreeBuilder parent, ActualParameter targetParameter, TypeData expectType) { |
2085 CodeTreeBuilder builder = parent.create(); | 2104 CodeTreeBuilder builder = parent.create(); |
2086 NodeData node = getModel().getNode(); | 2105 NodeData node = getModel().getNode(); |
2087 NodeChildData child = node.findChild(param.getSpecification().getName()); | 2106 NodeChildData child = node.findChild(targetParameter.getSpecification().getName()); |
2088 List<TypeData> sourceTypes = node.getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); | 2107 List<TypeData> sourceTypes = node.getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType()); |
2089 boolean elseIf = false; | 2108 boolean elseIf = false; |
2090 int index = 0; | 2109 int index = 0; |
2091 for (TypeData sourceType : sourceTypes) { | 2110 for (TypeData sourceType : sourceTypes) { |
2092 if (index < sourceTypes.size() - 1) { | 2111 if (index < sourceTypes.size() - 1) { |
2093 elseIf = builder.startIf(elseIf); | 2112 elseIf = builder.startIf(elseIf); |
2094 builder.string(typeName(param)).string(" == ").typeLiteral(sourceType.getPrimitiveType()); | 2113 builder.string(implicitTypeName(targetParameter)).string(" == ").typeLiteral(sourceType.getPrimitiveType()); |
2095 builder.end(); | 2114 builder.end(); |
2096 builder.startBlock(); | 2115 builder.startBlock(); |
2097 } else { | 2116 } else { |
2098 builder.startElseBlock(); | 2117 builder.startElseBlock(); |
2099 } | 2118 } |
2100 | 2119 |
2101 ExecutableTypeData implictExecutableTypeData = child.getNodeData().findExecutableType(sourceType, child.getExecuteWith().size()); | 2120 ExecutableTypeData implictExecutableTypeData = child.findExecutableType(getContext(), sourceType); |
2102 if (implictExecutableTypeData == null) { | 2121 if (implictExecutableTypeData == null) { |
2103 /* | 2122 /* |
2104 * For children with executeWith.size() > 0 an executable type may not exist so | 2123 * For children with executeWith.size() > 0 an executable type may not exist so |
2105 * use the generic executable type which is guaranteed to exist. An expect call | 2124 * use the generic executable type which is guaranteed to exist. An expect call |
2106 * is inserted automatically by #createExecuteExpression. | 2125 * is inserted automatically by #createExecuteExpression. |
2107 */ | 2126 */ |
2108 implictExecutableTypeData = child.getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), child.getExecuteWith().size()); | 2127 implictExecutableTypeData = child.getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), child.getExecuteWith().size()); |
2109 } | 2128 } |
2110 | 2129 |
2111 ImplicitCastData cast = child.getNodeData().getTypeSystem().lookupCast(sourceType, param.getTypeSystemType()); | 2130 ImplicitCastData cast = child.getNodeData().getTypeSystem().lookupCast(sourceType, targetParameter.getTypeSystemType()); |
2112 CodeTree execute = createExecuteExpression(builder, child, expectType, implictExecutableTypeData, param, null, cast); | 2131 CodeTree execute = createExecuteChildExpression(builder, child, expectType, targetParameter, null, cast); |
2113 builder.statement(execute); | 2132 builder.statement(execute); |
2114 builder.end(); | 2133 builder.end(); |
2115 index++; | 2134 index++; |
2116 } | 2135 } |
2117 return builder.getRoot(); | 2136 return builder.getRoot(); |
2118 } | 2137 } |
2119 | 2138 |
2120 private CodeTree createExecuteExpression(CodeTreeBuilder parent, NodeChildData child, TypeData expectType, ExecutableTypeData targetExecutable, ActualParameter targetParameter, | 2139 private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData child, TypeData sourceParameterType, ActualParameter targetParameter, ActualParameter unexpectedParameter, |
2121 ActualParameter unexpectedParameter, ImplicitCastData cast) { | 2140 ImplicitCastData cast) { |
2141 // assignments: targetType <- castTargetType <- castSourceType <- sourceType | |
2142 TypeData sourceType = sourceParameterType; | |
2143 TypeData targetType = targetParameter.getTypeSystemType(); | |
2144 TypeData castSourceType = targetType; | |
2145 TypeData castTargetType = targetType; | |
2146 | |
2147 if (cast != null) { | |
2148 castSourceType = cast.getSourceType(); | |
2149 castTargetType = cast.getTargetType(); | |
2150 } | |
2151 | |
2152 CodeTree expression; | |
2153 if (sourceType == null) { | |
2154 ExecutableTypeData targetExecutable = resolveExecutableType(child, targetType); | |
2155 expression = createExecuteChildExpression(parent, child, targetParameter, targetExecutable, unexpectedParameter); | |
2156 sourceType = targetExecutable.getType(); | |
2157 } else { | |
2158 expression = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)); | |
2159 } | |
2160 | |
2161 // target = expectTargetType(implicitCast(expectCastSourceType(source))) | |
2162 TypeSystemData typeSystem = child.getNodeData().getTypeSystem(); | |
2163 expression = createExpectType(typeSystem, sourceType, castSourceType, expression); | |
2164 expression = createImplicitCast(parent, typeSystem, cast, expression); | |
2165 expression = createExpectType(typeSystem, castTargetType, targetType, expression); | |
2166 | |
2122 CodeTreeBuilder builder = parent.create(); | 2167 CodeTreeBuilder builder = parent.create(); |
2123 builder.string(valueName(targetParameter)); | 2168 builder.string(valueName(targetParameter)); |
2124 builder.string(" = "); | 2169 builder.string(" = "); |
2125 if (cast != null) { | 2170 builder.tree(expression); |
2126 startCallTypeSystemMethod(getContext(), builder, child.getNodeData(), cast.getMethodName()); | 2171 return builder.getRoot(); |
2127 } | 2172 } |
2128 | 2173 |
2129 TypeData expectTarget = targetParameter.getTypeSystemType(); | 2174 private CodeTree createImplicitCast(CodeTreeBuilder parent, TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) { |
2130 if (cast != null) { | 2175 if (cast == null) { |
2131 expectTarget = cast.getSourceType(); | 2176 return expression; |
2132 } | 2177 } |
2133 | 2178 CodeTreeBuilder builder = parent.create(); |
2134 if (targetExecutable.getType().needsCastTo(context, expectTarget)) { | 2179 startCallTypeSystemMethod(getContext(), builder, typeSystem, cast.getMethodName()); |
2135 startCallTypeSystemMethod(getContext(), builder, child.getNodeData(), TypeSystemCodeGenerator.expectTypeMethodName(expectTarget)); | 2180 builder.tree(expression); |
2136 } | 2181 builder.end().end(); |
2137 | |
2138 NodeData node = getModel().getNode(); | |
2139 if (expectType == null) { | |
2140 builder.tree(createExecuteChildExpression(builder, child, targetParameter, targetExecutable, unexpectedParameter)); | |
2141 } else { | |
2142 CodeTree var = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)); | |
2143 builder.tree(createExpectExecutableType(node, expectType, targetExecutable, var)); | |
2144 } | |
2145 | |
2146 if (targetExecutable.getType().needsCastTo(context, targetParameter.getTypeSystemType())) { | |
2147 builder.end().end(); | |
2148 } | |
2149 | |
2150 if (cast != null) { | |
2151 builder.end().end(); | |
2152 } | |
2153 | |
2154 return builder.getRoot(); | 2182 return builder.getRoot(); |
2155 } | 2183 } |
2156 | 2184 |
2157 private boolean containsNewLine(CodeTree tree) { | 2185 private boolean containsNewLine(CodeTree tree) { |
2158 if (tree.getCodeKind() == CodeTreeKind.NEW_LINE) { | 2186 if (tree.getCodeKind() == CodeTreeKind.NEW_LINE) { |
2165 } | 2193 } |
2166 } | 2194 } |
2167 return false; | 2195 return false; |
2168 } | 2196 } |
2169 | 2197 |
2170 private boolean hasUnexpected(ExecutableTypeData target, ActualParameter sourceParameter, ActualParameter targetParameter) { | 2198 private boolean hasUnexpected(ActualParameter sourceParameter, ActualParameter targetParameter, ActualParameter unexpectedParameter) { |
2171 List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType()); | |
2172 NodeChildData child = getModel().getNode().findChild(targetParameter.getSpecification().getName()); | 2199 NodeChildData child = getModel().getNode().findChild(targetParameter.getSpecification().getName()); |
2173 boolean hasUnexpected = false; | 2200 |
2174 for (TypeData type : types) { | 2201 if (getModel().isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) { |
2175 if (hasUnexpected) { | 2202 // check for other polymorphic types |
2176 continue; | 2203 for (TypeData polymorphicTargetType : lookupPolymorphicTargetTypes(targetParameter)) { |
2177 } | 2204 if (hasUnexpectedType(child, sourceParameter, polymorphicTargetType)) { |
2178 ExecutableTypeData execTarget = target; | 2205 return true; |
2179 if (type != execTarget.getType()) { | 2206 } |
2180 execTarget = child.findExecutableType(getContext(), type); | 2207 } |
2181 } | 2208 } |
2182 hasUnexpected = hasUnexpected || hasUnexpectedType(execTarget, sourceParameter, type); | 2209 |
2183 } | 2210 if (hasUnexpectedType(child, sourceParameter, targetParameter.getTypeSystemType())) { |
2184 return hasUnexpected; | |
2185 } | |
2186 | |
2187 private boolean hasUnexpectedType(ExecutableTypeData target, ActualParameter sourceParameter, TypeData type) { | |
2188 boolean targetCast = target.getType().needsCastTo(context, type); | |
2189 if (targetCast && getModel().getNode().getTypeSystem().lookupCast(target.getType(), type) == null) { | |
2190 return true; | 2211 return true; |
2191 } | 2212 } |
2192 if (sourceParameter == null) { | 2213 return false; |
2193 return target.hasUnexpectedValue(getContext()); | 2214 } |
2194 } else { | 2215 |
2195 if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), type)) { | 2216 private boolean hasUnexpectedType(NodeChildData child, ActualParameter sourceParameter, TypeData targetType) { |
2196 return target.hasUnexpectedValue(getContext()); | 2217 List<TypeData> implicitSourceTypes = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); |
2197 } | 2218 |
2198 return false; | 2219 for (TypeData implicitSourceType : implicitSourceTypes) { |
2199 } | 2220 TypeData sourceType; |
2200 } | 2221 if (sourceParameter != null) { |
2201 | 2222 sourceType = sourceParameter.getTypeSystemType(); |
2202 private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ExecutableTypeData currentExecutable, | 2223 } else { |
2203 ExecutableTypeData targetExecutable, ActualParameter param, boolean shortCircuit) { | 2224 ExecutableTypeData targetExecutable = resolveExecutableType(child, implicitSourceType); |
2225 if (targetExecutable.hasUnexpectedValue(getContext())) { | |
2226 return true; | |
2227 } | |
2228 sourceType = targetExecutable.getType(); | |
2229 } | |
2230 | |
2231 ImplicitCastData cast = getModel().getNode().getTypeSystem().lookupCast(implicitSourceType, targetType); | |
2232 if (cast != null) { | |
2233 if (cast.getSourceType().needsCastTo(getContext(), targetType)) { | |
2234 return true; | |
2235 } | |
2236 } | |
2237 | |
2238 if (sourceType.needsCastTo(getContext(), targetType)) { | |
2239 return true; | |
2240 } | |
2241 } | |
2242 return false; | |
2243 } | |
2244 | |
2245 private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ExecutableTypeData currentExecutable, ActualParameter param, | |
2246 boolean shortCircuit, ActualParameter unexpectedParameter) { | |
2204 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 2247 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
2205 ActualParameter sourceParameter = currentExecutable.findParameter(param.getLocalName()); | 2248 ActualParameter sourceParameter = currentExecutable.findParameter(param.getLocalName()); |
2206 boolean unexpected = hasUnexpected(targetExecutable, sourceParameter, param); | 2249 boolean unexpected = hasUnexpected(sourceParameter, param, unexpectedParameter); |
2207 if (!unexpected) { | 2250 if (!unexpected) { |
2208 return body; | 2251 return body; |
2209 } | 2252 } |
2210 | 2253 |
2211 if (!shortCircuit) { | 2254 if (!shortCircuit) { |
2212 builder.declaration(param.getType(), targetVariableName); | 2255 builder.declaration(param.getType(), valueName(param)); |
2213 } | 2256 } |
2214 builder.startTryBlock(); | 2257 builder.startTryBlock(); |
2215 | 2258 |
2216 if (containsNewLine(body)) { | 2259 if (containsNewLine(body)) { |
2217 builder.tree(body); | 2260 builder.tree(body); |
2222 builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); | 2265 builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); |
2223 SpecializationData generic = specialization.getNode().getGenericSpecialization(); | 2266 SpecializationData generic = specialization.getNode().getGenericSpecialization(); |
2224 ActualParameter genericParameter = generic.findParameter(param.getLocalName()); | 2267 ActualParameter genericParameter = generic.findParameter(param.getLocalName()); |
2225 | 2268 |
2226 List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter); | 2269 List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter); |
2227 builder.tree(createDeoptimize(builder)); | |
2228 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter)); | 2270 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter)); |
2229 if (specialization.isPolymorphic()) { | 2271 if (specialization.isPolymorphic()) { |
2230 builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param)); | 2272 builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param)); |
2231 } else { | 2273 } else { |
2232 builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization, param, | 2274 builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization, param, |
2241 NodeData node = specialization.getNode(); | 2283 NodeData node = specialization.getNode(); |
2242 assert !node.getPolymorphicSpecializations().isEmpty(); | 2284 assert !node.getPolymorphicSpecializations().isEmpty(); |
2243 SpecializationData generic = node.getGenericPolymorphicSpecialization(); | 2285 SpecializationData generic = node.getGenericPolymorphicSpecialization(); |
2244 | 2286 |
2245 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 2287 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
2288 builder.startStatement().string(polymorphicTypeName(param)).string(" = ").typeLiteral(getContext().getType(Object.class)).end(); | |
2289 | |
2246 builder.startReturn(); | 2290 builder.startReturn(); |
2247 | 2291 |
2248 CodeTreeBuilder execute = new CodeTreeBuilder(builder); | 2292 CodeTreeBuilder execute = new CodeTreeBuilder(builder); |
2249 execute.startCall("next0", executeCachedName(generic)); | 2293 execute.startCall("next0", executeCachedName(generic)); |
2250 addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true, null); | 2294 addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true, null); |
2330 builder.string("[" + targetParameter.getIndex() + "]"); | 2374 builder.string("[" + targetParameter.getIndex() + "]"); |
2331 } | 2375 } |
2332 return builder.getRoot(); | 2376 return builder.getRoot(); |
2333 } | 2377 } |
2334 | 2378 |
2335 private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ActualParameter parameter, | 2379 private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) { |
2336 ActualParameter exceptionParam) { | |
2337 NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName()); | 2380 NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName()); |
2338 if (!isShortCircuit(forField)) { | 2381 if (!isShortCircuit(forField)) { |
2339 return body; | 2382 return body; |
2340 } | 2383 } |
2341 | 2384 |
2342 CodeTreeBuilder builder = new CodeTreeBuilder(parent); | 2385 CodeTreeBuilder builder = new CodeTreeBuilder(parent); |
2343 ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter); | 2386 ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter); |
2344 builder.tree(createShortCircuitValue(builder, specialization, forField, shortCircuitParam, exceptionParam)); | 2387 builder.tree(createShortCircuitValue(builder, specialization, forField, shortCircuitParam, exceptionParam)); |
2345 builder.declaration(parameter.getType(), targetVariableName, CodeTreeBuilder.createBuilder().defaultValue(parameter.getType())); | 2388 builder.declaration(parameter.getType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getType())); |
2346 builder.startIf().string(shortCircuitParam.getLocalName()).end(); | 2389 builder.startIf().string(shortCircuitParam.getLocalName()).end(); |
2347 builder.startBlock(); | 2390 builder.startBlock(); |
2348 | 2391 |
2349 if (containsNewLine(body)) { | 2392 if (containsNewLine(body)) { |
2350 builder.tree(body); | 2393 builder.tree(body); |
2404 builder.tree(createExpectExecutableType(node, generic.getReturnType().getTypeSystemType(), executable, specializeCall.getRoot())); | 2447 builder.tree(createExpectExecutableType(node, generic.getReturnType().getTypeSystemType(), executable, specializeCall.getRoot())); |
2405 builder.end(); | 2448 builder.end(); |
2406 | 2449 |
2407 return builder.getRoot(); | 2450 return builder.getRoot(); |
2408 } | 2451 } |
2452 | |
2453 protected final CodeExecutableElement createUpdateTypes(TypeMirror polymorphicType) { | |
2454 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getContext().getType(void.class), UPDATE_TYPES_NAME); | |
2455 method.getParameters().add(new CodeVariableElement(polymorphicType, "polymorphic")); | |
2456 CodeTreeBuilder builder = method.createBuilder(); | |
2457 | |
2458 if (getModel().isPolymorphic()) { | |
2459 builder.startStatement(); | |
2460 builder.startCall("next0", "updateTypes").string("polymorphic").end(); | |
2461 builder.end(); | |
2462 } else if (getModel().isSpecialized()) { | |
2463 for (ActualParameter parameter : getModel().getParameters()) { | |
2464 if (!parameter.getSpecification().isSignature()) { | |
2465 continue; | |
2466 } | |
2467 if (lookupPolymorphicTargetTypes(parameter).size() <= 1) { | |
2468 continue; | |
2469 } | |
2470 builder.startStatement(); | |
2471 builder.startCall("polymorphic", createUpdateTypeName(parameter)); | |
2472 builder.typeLiteral(parameter.getType()); | |
2473 builder.end().end(); | |
2474 } | |
2475 | |
2476 builder.startStatement().startCall("super", UPDATE_TYPES_NAME).string("polymorphic").end().end(); | |
2477 } | |
2478 return method; | |
2479 } | |
2480 | |
2481 protected String createUpdateTypeName(ActualParameter parameter) { | |
2482 return "update" + Utils.firstLetterUpperCase(parameter.getLocalName()) + "Type"; | |
2483 } | |
2409 } | 2484 } |
2410 | 2485 |
2411 private class PolymorphicNodeFactory extends SpecializedNodeFactory { | 2486 private class PolymorphicNodeFactory extends SpecializedNodeFactory { |
2412 | 2487 |
2413 private final boolean generic; | 2488 public PolymorphicNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) { |
2414 | |
2415 public PolymorphicNodeFactory(ProcessorContext context, CodeTypeElement nodeGen, boolean generic) { | |
2416 super(context, nodeGen); | 2489 super(context, nodeGen); |
2417 this.generic = generic; | 2490 } |
2491 | |
2492 @Override | |
2493 public CodeTypeElement create(SpecializationData polymorph) { | |
2494 NodeData node = polymorph.getNode(); | |
2495 TypeMirror baseType = node.getNodeType(); | |
2496 if (nodeGen != null) { | |
2497 baseType = nodeGen.asType(); | |
2498 } | |
2499 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node, polymorph), baseType, false); | |
2500 | |
2501 clazz.getAnnotationMirrors().add(createNodeInfo(node, Kind.POLYMORPHIC)); | |
2502 | |
2503 for (ActualParameter polymorphParameter : polymorph.getParameters()) { | |
2504 if (!polymorphParameter.getSpecification().isSignature()) { | |
2505 continue; | |
2506 } | |
2507 if (!polymorphParameter.getTypeSystemType().isGeneric()) { | |
2508 continue; | |
2509 } | |
2510 Set<TypeData> types = new HashSet<>(); | |
2511 for (SpecializationData specialization : node.getSpecializations()) { | |
2512 if (!specialization.isSpecialized()) { | |
2513 continue; | |
2514 } | |
2515 ActualParameter parameter = specialization.findParameter(polymorphParameter.getLocalName()); | |
2516 assert parameter != null; | |
2517 types.add(parameter.getTypeSystemType()); | |
2518 } | |
2519 CodeVariableElement var = new CodeVariableElement(modifiers(PRIVATE), getContext().getType(Class.class), polymorphicTypeName(polymorphParameter)); | |
2520 var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getCompilationFinal())); | |
2521 clazz.add(var); | |
2522 } | |
2523 | |
2524 return clazz; | |
2525 } | |
2526 | |
2527 @Override | |
2528 protected void createChildren(SpecializationData specialization) { | |
2529 CodeTypeElement clazz = getElement(); | |
2530 | |
2531 createConstructors(clazz); | |
2532 createExecuteMethods(specialization); | |
2533 | |
2534 getElement().add(createUpdateTypes(nodeGen.asType())); | |
2535 | |
2536 for (ActualParameter parameter : specialization.getParameters()) { | |
2537 if (!parameter.getSpecification().isSignature()) { | |
2538 continue; | |
2539 } | |
2540 if (lookupPolymorphicTargetTypes(parameter).size() <= 1) { | |
2541 continue; | |
2542 } | |
2543 getElement().add(createUpdateType(parameter)); | |
2544 } | |
2545 | |
2546 createCachedExecuteMethods(specialization); | |
2547 | |
2548 } | |
2549 | |
2550 private ExecutableElement createUpdateType(ActualParameter parameter) { | |
2551 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getContext().getType(void.class), createUpdateTypeName(parameter)); | |
2552 method.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), "type")); | |
2553 CodeTreeBuilder builder = method.createBuilder(); | |
2554 | |
2555 String fieldName = polymorphicTypeName(parameter); | |
2556 builder.startIf().string(fieldName).isNull().end().startBlock(); | |
2557 builder.startStatement().string(fieldName).string(" = ").string("type").end(); | |
2558 builder.end(); | |
2559 builder.startElseIf().string(fieldName).string(" != ").string("type").end(); | |
2560 builder.startBlock(); | |
2561 builder.startStatement().string(fieldName).string(" = ").typeLiteral(getContext().getType(Object.class)).end(); | |
2562 builder.end(); | |
2563 | |
2564 return method; | |
2565 } | |
2566 | |
2567 } | |
2568 | |
2569 private class SpecializedNodeFactory extends NodeBaseFactory { | |
2570 | |
2571 protected final CodeTypeElement nodeGen; | |
2572 | |
2573 public SpecializedNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) { | |
2574 super(context); | |
2575 this.nodeGen = nodeGen; | |
2418 } | 2576 } |
2419 | 2577 |
2420 @Override | 2578 @Override |
2421 public CodeTypeElement create(SpecializationData specialization) { | 2579 public CodeTypeElement create(SpecializationData specialization) { |
2422 NodeData node = specialization.getNode(); | 2580 NodeData node = specialization.getNode(); |
2423 TypeMirror baseType = node.getNodeType(); | 2581 TypeMirror baseType = node.getNodeType(); |
2424 if (nodeGen != null) { | 2582 if (nodeGen != null) { |
2425 baseType = nodeGen.asType(); | 2583 baseType = nodeGen.asType(); |
2426 } | 2584 } |
2427 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC), nodePolymorphicClassName(node, specialization), baseType, false); | |
2428 | |
2429 if (!generic) { | |
2430 clazz.getModifiers().add(Modifier.FINAL); | |
2431 } | |
2432 | |
2433 clazz.getAnnotationMirrors().add(createNodeInfo(node, Kind.POLYMORPHIC)); | |
2434 | |
2435 return clazz; | |
2436 } | |
2437 | |
2438 @Override | |
2439 protected void createChildren(SpecializationData specialization) { | |
2440 CodeTypeElement clazz = getElement(); | |
2441 | |
2442 createConstructors(clazz); | |
2443 createExecuteMethods(specialization); | |
2444 | |
2445 if (generic) { | |
2446 getElement().add(createOptimizeTypes()); | |
2447 createCachedExecuteMethods(specialization); | |
2448 createIsCompatible(clazz, specialization); | |
2449 } | |
2450 } | |
2451 | |
2452 private CodeExecutableElement createOptimizeTypes() { | |
2453 NodeData node = getModel().getNode(); | |
2454 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), getContext().getType(void.class), "optimizeTypes"); | |
2455 CodeTreeBuilder builder = method.createBuilder(); | |
2456 | |
2457 boolean elseIf = false; | |
2458 for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) { | |
2459 String className = nodePolymorphicClassName(node, polymorphic); | |
2460 | |
2461 String sep = ""; | |
2462 StringBuilder reason = new StringBuilder("Optimized polymorphic types for ("); | |
2463 for (ActualParameter parameter : polymorphic.getReturnTypeAndParameters()) { | |
2464 if (!parameter.getSpecification().isSignature()) { | |
2465 continue; | |
2466 } | |
2467 reason.append(sep).append(Utils.getSimpleName(parameter.getType())); | |
2468 sep = ", "; | |
2469 } | |
2470 reason.append(")"); | |
2471 | |
2472 elseIf = builder.startIf(elseIf); | |
2473 builder.startCall("isCompatible0"); | |
2474 builder.startGroup().string(className).string(".class").end(); | |
2475 builder.end().end().startBlock(); | |
2476 | |
2477 builder.startStatement().startCall("super", "replace"); | |
2478 builder.startNew(className).string("this").end(); | |
2479 builder.doubleQuote(reason.toString()); | |
2480 builder.end().end(); // call | |
2481 builder.end(); | |
2482 } | |
2483 return method; | |
2484 } | |
2485 } | |
2486 | |
2487 private class BaseCastNodeFactory extends ClassElementFactory<NodeData> { | |
2488 | |
2489 protected final Set<TypeData> usedTargetTypes; | |
2490 | |
2491 public BaseCastNodeFactory(ProcessorContext context, Set<TypeData> usedTargetTypes) { | |
2492 super(context); | |
2493 this.usedTargetTypes = usedTargetTypes; | |
2494 } | |
2495 | |
2496 @Override | |
2497 protected CodeTypeElement create(NodeData m) { | |
2498 CodeTypeElement type = createClass(m, modifiers(STATIC), nodeCastClassName(m, null), context.getTruffleTypes().getNode(), false); | |
2499 | |
2500 CodeVariableElement delegate = new CodeVariableElement(m.getNodeType(), "delegate"); | |
2501 delegate.getModifiers().add(PROTECTED); | |
2502 delegate.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation())); | |
2503 | |
2504 type.add(delegate); | |
2505 type.add(createConstructorUsingFields(modifiers(), type)); | |
2506 return type; | |
2507 } | |
2508 | |
2509 @Override | |
2510 protected void createChildren(NodeData m) { | |
2511 CodeTypeElement type = getElement(); | |
2512 type.add(createExecute(EXECUTE_SPECIALIZE_NAME, true)); | |
2513 type.add(createExecute(EXECUTE_GENERIC_NAME, false)); | |
2514 | |
2515 for (ExecutableTypeData targetExecutable : m.getExecutableTypes()) { | |
2516 if (!usedTargetTypes.contains(targetExecutable.getType()) && targetExecutable.hasUnexpectedValue(getContext())) { | |
2517 continue; | |
2518 } | |
2519 CodeExecutableElement execute = createCastExecute(targetExecutable, targetExecutable, false); | |
2520 CodeExecutableElement expect = createCastExecute(targetExecutable, targetExecutable, true); | |
2521 if (execute != null) { | |
2522 getElement().add(execute); | |
2523 } | |
2524 if (expect != null) { | |
2525 getElement().add(expect); | |
2526 } | |
2527 } | |
2528 Set<TypeData> sourceTypes = new TreeSet<>(); | |
2529 List<ImplicitCastData> casts = getModel().getTypeSystem().getImplicitCasts(); | |
2530 for (ImplicitCastData cast : casts) { | |
2531 sourceTypes.add(cast.getSourceType()); | |
2532 } | |
2533 | |
2534 CodeTypeElement baseType = getElement(); | |
2535 for (TypeData sourceType : sourceTypes) { | |
2536 add(new SpecializedCastNodeFactory(context, baseType, sourceType, usedTargetTypes), getModel()); | |
2537 } | |
2538 } | |
2539 | |
2540 private CodeExecutableElement createExecute(String name, boolean specialize) { | |
2541 NodeData node = getModel(); | |
2542 TypeMirror objectType = node.getTypeSystem().getGenericType(); | |
2543 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), objectType, name, new CodeVariableElement(objectType, "value")); | |
2544 if (specialize) { | |
2545 method.getModifiers().add(FINAL); | |
2546 } | |
2547 CodeTreeBuilder builder = method.createBuilder(); | |
2548 | |
2549 List<ImplicitCastData> casts = node.getTypeSystem().getImplicitCasts(); | |
2550 boolean elseIf = false; | |
2551 for (ImplicitCastData cast : casts) { | |
2552 elseIf = builder.startIf(elseIf); | |
2553 startCallTypeSystemMethod(context, builder, getModel(), TypeSystemCodeGenerator.isTypeMethodName(cast.getSourceType())); | |
2554 builder.string("value"); | |
2555 builder.end().end(); | |
2556 builder.end(); | |
2557 builder.startBlock(); | |
2558 | |
2559 if (specialize) { | |
2560 builder.startStatement().startCall("replace").startNew(nodeCastClassName(getModel(), cast.getSourceType())).string("delegate").end().doubleQuote("Added cast").end().end(); | |
2561 } | |
2562 builder.startReturn(); | |
2563 | |
2564 startCallTypeSystemMethod(context, builder, getModel(), cast.getMethodName()); | |
2565 startCallTypeSystemMethod(context, builder, getModel(), TypeSystemCodeGenerator.asTypeMethodName(cast.getSourceType())); | |
2566 builder.string("value"); | |
2567 builder.end().end(); | |
2568 builder.end().end(); | |
2569 | |
2570 builder.end(); | |
2571 builder.end(); | |
2572 } | |
2573 | |
2574 builder.startReturn().string("value").end(); | |
2575 | |
2576 return method; | |
2577 } | |
2578 | |
2579 protected CodeExecutableElement createCastExecute(ExecutableTypeData sourceExecutable, ExecutableTypeData targetExecutable, boolean expect) { | |
2580 ImplicitCastData cast = null; | |
2581 if (!sourceExecutable.getType().equals(targetExecutable.getType())) { | |
2582 cast = getModel().getTypeSystem().lookupCast(sourceExecutable.getType(), targetExecutable.getType()); | |
2583 if (cast == null) { | |
2584 return null; | |
2585 } | |
2586 } | |
2587 | |
2588 if (expect) { | |
2589 if (targetExecutable.getEvaluatedCount() > 0) { | |
2590 return null; | |
2591 } else if (Utils.isObject(targetExecutable.getType().getPrimitiveType())) { | |
2592 return null; | |
2593 } | |
2594 } | |
2595 | |
2596 boolean hasTargetUnexpected = targetExecutable.hasUnexpectedValue(getContext()); | |
2597 boolean hasSourceUnexpected = sourceExecutable.hasUnexpectedValue(getContext()); | |
2598 | |
2599 CodeExecutableElement method = copyTemplateMethod(targetExecutable); | |
2600 method.getModifiers().add(PUBLIC); | |
2601 | |
2602 CodeTreeBuilder builder = method.createBuilder(); | |
2603 | |
2604 if (hasSourceUnexpected && cast != null) { | |
2605 builder.startTryBlock(); | |
2606 } | |
2607 | |
2608 if (expect) { | |
2609 method.getParameters().clear(); | |
2610 String expectMethodName; | |
2611 if (hasTargetUnexpected) { | |
2612 expectMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetExecutable.getType()); | |
2613 } else { | |
2614 expectMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetExecutable.getType()); | |
2615 } | |
2616 method.setSimpleName(CodeNames.of(expectMethodName)); | |
2617 method.addParameter(new CodeVariableElement(getModel().getTypeSystem().getGenericType(), "value")); | |
2618 } | |
2619 | |
2620 builder.startReturn(); | |
2621 CodeTree executeCall; | |
2622 if (expect) { | |
2623 executeCall = createCastType(getModel(), getModel().getTypeSystem().getGenericTypeData(), sourceExecutable.getType(), hasSourceUnexpected, CodeTreeBuilder.singleString("value")); | |
2624 } else { | |
2625 executeCall = createTemplateMethodCall(builder, CodeTreeBuilder.singleString("delegate."), targetExecutable, sourceExecutable, null); | |
2626 } | |
2627 if (cast != null) { | |
2628 startCallTypeSystemMethod(context, builder, getModel(), cast.getMethodName()); | |
2629 builder.tree(executeCall); | |
2630 builder.end().end(); | |
2631 } else { | |
2632 builder.tree(executeCall); | |
2633 } | |
2634 builder.end(); | |
2635 | |
2636 if (hasSourceUnexpected && cast != null) { | |
2637 builder.end(); | |
2638 builder.startCatchBlock(getContext().getTruffleTypes().getUnexpectedValueException(), "ex"); | |
2639 builder.startStatement().startCall("replace").startNew(nodeCastClassName(getModel(), null)).string("delegate").end().doubleQuote("Removed cast").end().end(); | |
2640 | |
2641 if (hasTargetUnexpected) { | |
2642 builder.startThrow().string("ex").end(); | |
2643 } else { | |
2644 builder.startThrow().startNew(getContext().getType(AssertionError.class)).end().end(); | |
2645 } | |
2646 builder.end(); | |
2647 } | |
2648 | |
2649 return method; | |
2650 } | |
2651 | |
2652 private CodeExecutableElement copyTemplateMethod(TemplateMethod targetExecutable) { | |
2653 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), targetExecutable.getMethod()); | |
2654 method.getModifiers().remove(ABSTRACT); | |
2655 method.getAnnotationMirrors().clear(); | |
2656 Modifier visibility = Utils.getVisibility(method.getModifiers()); | |
2657 if (visibility != null) { | |
2658 method.getModifiers().remove(visibility); | |
2659 } | |
2660 int index = 0; | |
2661 for (ActualParameter parameter : targetExecutable.getParameters()) { | |
2662 ((CodeVariableElement) method.getParameters().get(index)).setName(parameter.getLocalName()); | |
2663 index++; | |
2664 } | |
2665 return method; | |
2666 } | |
2667 | |
2668 } | |
2669 | |
2670 private class SpecializedCastNodeFactory extends BaseCastNodeFactory { | |
2671 | |
2672 private final CodeTypeElement baseType; | |
2673 private final TypeData sourceType; | |
2674 | |
2675 public SpecializedCastNodeFactory(ProcessorContext context, CodeTypeElement baseType, TypeData type, Set<TypeData> usedTargetTypes) { | |
2676 super(context, usedTargetTypes); | |
2677 this.baseType = baseType; | |
2678 this.sourceType = type; | |
2679 } | |
2680 | |
2681 @Override | |
2682 protected CodeTypeElement create(NodeData m) { | |
2683 CodeTypeElement type = createClass(m, modifiers(PRIVATE, STATIC, FINAL), nodeCastClassName(m, sourceType), baseType.asType(), false); | |
2684 type.add(createConstructorUsingFields(modifiers(), type)); | |
2685 return type; | |
2686 } | |
2687 | |
2688 @Override | |
2689 protected void createChildren(NodeData node) { | |
2690 for (TypeData targetType : usedTargetTypes) { | |
2691 for (ExecutableTypeData targetExecutable : node.getExecutableTypes()) { | |
2692 if (targetExecutable.getType().equals(targetType)) { | |
2693 ExecutableTypeData sourceExecutable = node.findExecutableType(sourceType, targetExecutable.getEvaluatedCount()); | |
2694 if (sourceExecutable == null) { | |
2695 // TODO what if there is no evaluated version? | |
2696 continue; | |
2697 } | |
2698 CodeExecutableElement execute = createCastExecute(sourceExecutable, targetExecutable, false); | |
2699 CodeExecutableElement expect = createCastExecute(sourceExecutable, targetExecutable, true); | |
2700 if (execute != null) { | |
2701 getElement().add(execute); | |
2702 } | |
2703 if (expect != null) { | |
2704 getElement().add(expect); | |
2705 } | |
2706 } | |
2707 } | |
2708 | |
2709 } | |
2710 } | |
2711 | |
2712 } | |
2713 | |
2714 private class SpecializedNodeFactory extends NodeBaseFactory { | |
2715 | |
2716 protected final CodeTypeElement nodeGen; | |
2717 | |
2718 public SpecializedNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) { | |
2719 super(context); | |
2720 this.nodeGen = nodeGen; | |
2721 } | |
2722 | |
2723 @Override | |
2724 public CodeTypeElement create(SpecializationData specialization) { | |
2725 NodeData node = specialization.getNode(); | |
2726 TypeMirror baseType = node.getNodeType(); | |
2727 if (nodeGen != null) { | |
2728 baseType = nodeGen.asType(); | |
2729 } | |
2730 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false); | 2585 CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false); |
2731 | 2586 |
2732 Kind kind; | 2587 Kind kind; |
2733 if (specialization.isGeneric()) { | 2588 if (specialization.isGeneric()) { |
2734 kind = Kind.GENERIC; | 2589 kind = Kind.GENERIC; |
2759 @Override | 2614 @Override |
2760 protected void createChildren(SpecializationData specialization) { | 2615 protected void createChildren(SpecializationData specialization) { |
2761 CodeTypeElement clazz = getElement(); | 2616 CodeTypeElement clazz = getElement(); |
2762 createConstructors(clazz); | 2617 createConstructors(clazz); |
2763 | 2618 |
2764 NodeData node = specialization.getNode(); | |
2765 | |
2766 if (node.needsRewrites(getContext()) && node.isPolymorphic()) { | |
2767 createIsCompatible(clazz, specialization); | |
2768 } | |
2769 | |
2770 createExecuteMethods(specialization); | 2619 createExecuteMethods(specialization); |
2771 createCachedExecuteMethods(specialization); | 2620 createCachedExecuteMethods(specialization); |
2621 if (specialization.getNode().isPolymorphic()) { | |
2622 getElement().add(createUpdateTypes(nodeGen.asType())); | |
2623 } | |
2772 } | 2624 } |
2773 | 2625 |
2774 protected void createConstructors(CodeTypeElement clazz) { | 2626 protected void createConstructors(CodeTypeElement clazz) { |
2775 TypeElement superTypeElement = Utils.fromTypeMirror(clazz.getSuperclass()); | 2627 TypeElement superTypeElement = Utils.fromTypeMirror(clazz.getSuperclass()); |
2776 SpecializationData specialization = getModel(); | 2628 SpecializationData specialization = getModel(); |
2803 continue; | 2655 continue; |
2804 } | 2656 } |
2805 NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); | 2657 NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); |
2806 List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); | 2658 List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); |
2807 if (types.size() > 1) { | 2659 if (types.size() > 1) { |
2808 clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), typeName(param))); | 2660 clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param))); |
2809 superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), typeName(param))); | 2661 superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param))); |
2810 | 2662 |
2811 builder.startStatement(); | 2663 builder.startStatement(); |
2812 builder.string("this.").string(typeName(param)).string(" = ").string(typeName(param)); | 2664 builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param)); |
2813 builder.end(); | 2665 builder.end(); |
2814 } | 2666 } |
2815 } | 2667 } |
2816 | 2668 |
2817 clazz.add(superConstructor); | 2669 clazz.add(superConstructor); |
2839 } | 2691 } |
2840 } | 2692 } |
2841 | 2693 |
2842 protected void createCachedExecuteMethods(SpecializationData specialization) { | 2694 protected void createCachedExecuteMethods(SpecializationData specialization) { |
2843 NodeData node = specialization.getNode(); | 2695 NodeData node = specialization.getNode(); |
2696 if (!node.isPolymorphic()) { | |
2697 return; | |
2698 } | |
2699 | |
2844 CodeTypeElement clazz = getElement(); | 2700 CodeTypeElement clazz = getElement(); |
2845 for (final SpecializationData polymorphic : node.getPolymorphicSpecializations()) { | 2701 |
2846 if (!specialization.getSignature().isCompatibleTo(polymorphic.getSignature())) { | 2702 final SpecializationData polymorphic = node.getGenericPolymorphicSpecialization(); |
2847 continue; | 2703 |
2848 } | 2704 ExecutableElement executeCached = nodeGen.getMethod(executeCachedName(polymorphic)); |
2849 ExecutableElement executeCached = nodeGen.getMethod(executeCachedName(polymorphic)); | 2705 // ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached, |
2850 ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached, node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType()); | 2706 // node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType()); |
2851 | 2707 |
2852 CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, false); | 2708 ExecutableTypeMethodParser parser = new ExecutableTypeMethodParser(getContext(), node); |
2853 CodeTreeBuilder builder = executeMethod.createBuilder(); | 2709 ExecutableTypeData execType = parser.parse(Arrays.asList(executeCached)).get(0); |
2854 | 2710 |
2855 if (specialization.isGeneric() || specialization.isPolymorphic()) { | 2711 CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, false); |
2856 builder.startThrow().startNew(getContext().getType(AssertionError.class)); | 2712 CodeTreeBuilder builder = executeMethod.createBuilder(); |
2857 builder.doubleQuote("Should not be reached."); | 2713 |
2858 builder.end().end(); | 2714 if (specialization.isGeneric() || specialization.isPolymorphic()) { |
2859 } else if (specialization.isUninitialized()) { | 2715 builder.startThrow().startNew(getContext().getType(AssertionError.class)); |
2860 builder.tree(createAppendPolymorphic(builder, specialization)); | 2716 builder.doubleQuote("Should not be reached."); |
2861 } else { | 2717 builder.end().end(); |
2862 CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); | 2718 } else if (specialization.isUninitialized()) { |
2863 elseBuilder.startReturn().startCall("this.next0", executeCachedName(polymorphic)); | 2719 builder.tree(createAppendPolymorphic(builder, specialization)); |
2864 addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true, null); | 2720 } else { |
2865 elseBuilder.end().end(); | 2721 CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); |
2866 | 2722 elseBuilder.startReturn().startCall("this.next0", executeCachedName(polymorphic)); |
2867 boolean forceElse = specialization.getExceptions().size() > 0; | 2723 addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true, null); |
2868 builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() { | 2724 elseBuilder.end().end(); |
2869 | 2725 |
2870 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { | 2726 boolean forceElse = specialization.getExceptions().size() > 0; |
2871 return createGenericInvoke(b, polymorphic, current); | 2727 builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() { |
2872 } | 2728 |
2873 }, elseBuilder.getRoot(), forceElse, true)); | 2729 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { |
2874 } | 2730 return createGenericInvoke(b, polymorphic, current); |
2875 clazz.add(executeMethod); | 2731 } |
2876 } | 2732 }, elseBuilder.getRoot(), forceElse, true, true)); |
2733 } | |
2734 clazz.add(executeMethod); | |
2877 } | 2735 } |
2878 | 2736 |
2879 private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) { | 2737 private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) { |
2880 NodeData node = specialization.getNode(); | 2738 NodeData node = specialization.getNode(); |
2881 | 2739 |
2907 specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end(); | 2765 specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end(); |
2908 specializeCall.end().end(); | 2766 specializeCall.end().end(); |
2909 | 2767 |
2910 builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot()); | 2768 builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot()); |
2911 | 2769 |
2770 CodeTree root = builder.create().cast(nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).string("root").getRoot(); | |
2912 builder.startIf().string("this.next0 != null").end().startBlock(); | 2771 builder.startIf().string("this.next0 != null").end().startBlock(); |
2913 builder.startStatement().string("(").cast(nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).string("root).optimizeTypes()").end(); | 2772 builder.startStatement().string("(").tree(root).string(").").startCall(UPDATE_TYPES_NAME).tree(root).end().end(); |
2914 builder.end(); | 2773 builder.end(); |
2915 | 2774 |
2916 if (Utils.isVoid(builder.findMethod().getReturnType())) { | 2775 if (Utils.isVoid(builder.findMethod().getReturnType())) { |
2917 builder.returnStatement(); | 2776 builder.returnStatement(); |
2918 } else { | 2777 } else { |
3024 builder.tree(createExecuteTree(builder, specialization, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() { | 2883 builder.tree(createExecuteTree(builder, specialization, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() { |
3025 | 2884 |
3026 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { | 2885 public CodeTree create(CodeTreeBuilder b, SpecializationData current) { |
3027 return createExecute(b, executable, specialization); | 2886 return createExecute(b, executable, specialization); |
3028 } | 2887 } |
3029 }, returnSpecialized, false, false)); | 2888 }, returnSpecialized, false, false, false)); |
3030 | 2889 |
3031 return builder.getRoot(); | 2890 return builder.getRoot(); |
3032 } | 2891 } |
3033 | 2892 |
3034 private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { | 2893 private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { |