comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java @ 11545:2fb276f5e3e9

Truffle-DSL: implemented implicit casts.
author Christian Humer <christian.humer@gmail.com>
date Fri, 06 Sep 2013 16:16:40 +0200
parents dcaf879d4a7e
children 5d5007c9a5aa
comparison
equal deleted inserted replaced
11544:e5b5a5cb0ac7 11545:2fb276f5e3e9
60 60
61 private static String factoryClassName(NodeData node) { 61 private static String factoryClassName(NodeData node) {
62 return node.getNodeId() + "Factory"; 62 return node.getNodeId() + "Factory";
63 } 63 }
64 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 }
73
65 private static String nodeSpecializationClassName(SpecializationData specialization) { 74 private static String nodeSpecializationClassName(SpecializationData specialization) {
66 String nodeid = specialization.getNode().getNodeId(); 75 String nodeid = resolveNodeId(specialization.getNode());
67 if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
68 nodeid = nodeid.substring(0, nodeid.length() - 4);
69 }
70
71 String name = Utils.firstLetterUpperCase(nodeid); 76 String name = Utils.firstLetterUpperCase(nodeid);
72 name += Utils.firstLetterUpperCase(specialization.getId()); 77 name += Utils.firstLetterUpperCase(specialization.getId());
73 name += "Node"; 78 name += "Node";
74 return name; 79 return name;
75 } 80 }
76 81
77 private static String nodePolymorphicClassName(NodeData node, SpecializationData specialization) { 82 private static String nodePolymorphicClassName(NodeData node, SpecializationData specialization) {
78 String nodeid = node.getNodeId(); 83 String nodeid = resolveNodeId(node);
79 if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
80 nodeid = nodeid.substring(0, nodeid.length() - 4);
81 }
82 84
83 String name = Utils.firstLetterUpperCase(nodeid); 85 String name = Utils.firstLetterUpperCase(nodeid);
84 if (specialization == node.getGenericPolymorphicSpecialization()) { 86 if (specialization == node.getGenericPolymorphicSpecialization()) {
85 name += "PolymorphicNode"; 87 name += "PolymorphicNode";
86 } else { 88 } else {
87 name += "Polymorphic" + polymorphicIndex(node, specialization) + "Node"; 89 name += "Polymorphic" + polymorphicIndex(node, specialization) + "Node";
88 } 90 }
89 return name; 91 return name;
90 } 92 }
91 93
94 private static String resolveNodeId(NodeData node) {
95 String nodeid = node.getNodeId();
96 if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
97 nodeid = nodeid.substring(0, nodeid.length() - 4);
98 }
99 return nodeid;
100 }
101
92 private static String valueNameEvaluated(ActualParameter targetParameter) { 102 private static String valueNameEvaluated(ActualParameter targetParameter) {
93 return valueName(targetParameter) + "Evaluated"; 103 return valueName(targetParameter) + "Evaluated";
104 }
105
106 private static String typeName(ActualParameter param) {
107 return param.getLocalName() + "Type";
94 } 108 }
95 109
96 private static String valueName(ActualParameter param) { 110 private static String valueName(ActualParameter param) {
97 return param.getLocalName(); 111 return param.getLocalName();
98 } 112 }
145 159
146 method.addParameter(new CodeVariableElement(parameter.getType(), name)); 160 method.addParameter(new CodeVariableElement(parameter.getType(), name));
147 } 161 }
148 } 162 }
149 163
150 private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeImplicit) { 164 private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeImplicit,
165 Map<String, String> customNames) {
151 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { 166 if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
152 builder.string("frameValue"); 167 builder.string("frameValue");
153 } 168 }
154 for (ActualParameter parameter : specialization.getParameters()) { 169 for (ActualParameter parameter : specialization.getParameters()) {
155 ParameterSpec spec = parameter.getSpecification(); 170 ParameterSpec spec = parameter.getSpecification();
164 continue; 179 continue;
165 } 180 }
166 181
167 ActualParameter sourceParameter = source.findParameter(parameter.getLocalName()); 182 ActualParameter sourceParameter = source.findParameter(parameter.getLocalName());
168 183
169 if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) { 184 if (customNames != null && customNames.containsKey(parameter.getLocalName())) {
185 builder.string(customNames.get(parameter.getLocalName()));
186 } else if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) {
170 builder.cast(parameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); 187 builder.cast(parameter.getType(), CodeTreeBuilder.singleString("ex.getResult()"));
171 } else if (sourceParameter != null) { 188 } else if (sourceParameter != null) {
172 builder.string(valueName(sourceParameter, parameter)); 189 builder.string(valueName(sourceParameter, parameter));
173 } else { 190 } else {
174 builder.string(valueName(parameter)); 191 builder.string(valueName(parameter));
296 313
297 return builder.getRoot(); 314 return builder.getRoot();
298 } 315 }
299 316
300 private static String baseClassName(NodeData node) { 317 private static String baseClassName(NodeData node) {
301 String nodeid = node.getNodeId(); 318 String nodeid = resolveNodeId(node);
302 if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
303 nodeid = nodeid.substring(0, nodeid.length() - 4);
304 }
305 String name = Utils.firstLetterUpperCase(nodeid); 319 String name = Utils.firstLetterUpperCase(nodeid);
306 name += "BaseNode"; 320 name += "BaseNode";
307 return name; 321 return name;
308 } 322 }
309 323
360 374
361 protected void emitEncounteredSynthetic(CodeTreeBuilder builder, TemplateMethod current) { 375 protected void emitEncounteredSynthetic(CodeTreeBuilder builder, TemplateMethod current) {
362 builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)); 376 builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class));
363 builder.startCall("createInfo0"); 377 builder.startCall("createInfo0");
364 builder.doubleQuote("Unsupported values"); 378 builder.doubleQuote("Unsupported values");
365 addInternalValueParameterNames(builder, current, current, null, false, true); 379 addInternalValueParameterNames(builder, current, current, null, false, true, null);
366 builder.end().end().end(); 380 builder.end().end().end();
367 } 381 }
368 382
369 private static List<ExecutableElement> findUserConstructors(TypeMirror nodeType) { 383 private static List<ExecutableElement> findUserConstructors(TypeMirror nodeType) {
370 List<ExecutableElement> constructors = new ArrayList<>(); 384 List<ExecutableElement> constructors = new ArrayList<>();
420 } 434 }
421 return false; 435 return false;
422 } 436 }
423 437
424 @Override 438 @Override
439 @SuppressWarnings("unchecked")
425 protected void createChildren(NodeData node) { 440 protected void createChildren(NodeData node) {
441 List<CodeTypeElement> casts = new ArrayList<>(getElement().getEnclosedElements());
442 getElement().getEnclosedElements().clear();
443
426 Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>(); 444 Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>();
427 if (node.getDeclaredNodes() != null && !node.getDeclaredNodes().isEmpty()) { 445 if (node.getDeclaredNodes() != null && !node.getDeclaredNodes().isEmpty()) {
428 for (NodeData nodeChild : node.getDeclaredNodes()) { 446 for (NodeData nodeChild : node.getDeclaredNodes()) {
429 NodeCodeGenerator generator = new NodeCodeGenerator(getContext()); 447 NodeCodeGenerator generator = new NodeCodeGenerator(getContext());
430 childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements()); 448 childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements());
431 } 449 }
432 } 450 }
433 451
434 if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) { 452 if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) {
435 add(new NodeFactoryFactory(context, childTypes), node); 453 NodeFactoryFactory factory = new NodeFactoryFactory(context, childTypes);
436 } 454 add(factory, node);
455 factory.getElement().getEnclosedElements().addAll(casts);
456 }
457 }
458
459 protected CodeTree createCastType(NodeData node, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) {
460 if (targetType == null) {
461 return value;
462 } else if (sourceType != null && !sourceType.needsCastTo(getContext(), targetType)) {
463 return value;
464 }
465
466 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
467 String targetMethodName;
468 if (expect) {
469 targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType);
470 } else {
471 targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
472 }
473 startCallTypeSystemMethod(getContext(), builder, node, targetMethodName);
474 builder.tree(value);
475 builder.end().end();
476 return builder.getRoot();
437 } 477 }
438 478
439 private class NodeFactoryFactory extends ClassElementFactory<NodeData> { 479 private class NodeFactoryFactory extends ClassElementFactory<NodeData> {
440 480
441 private final Map<NodeData, List<TypeElement>> childTypes; 481 private final Map<NodeData, List<TypeElement>> childTypes;
442
443 private CodeTypeElement generatedNode; 482 private CodeTypeElement generatedNode;
444 483
445 public NodeFactoryFactory(ProcessorContext context, Map<NodeData, List<TypeElement>> childElements) { 484 public NodeFactoryFactory(ProcessorContext context, Map<NodeData, List<TypeElement>> childElements) {
446 super(context); 485 super(context);
447 this.childTypes = childElements; 486 this.childTypes = childElements;
851 890
852 if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) { 891 if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) {
853 ExecutableElement getter = (ExecutableElement) child.getAccessElement(); 892 ExecutableElement getter = (ExecutableElement) child.getAccessElement();
854 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter); 893 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter);
855 method.getModifiers().remove(Modifier.ABSTRACT); 894 method.getModifiers().remove(Modifier.ABSTRACT);
856 method.createBuilder().startReturn().string("this.").string(child.getName()).end(); 895 CodeTreeBuilder builder = method.createBuilder();
896 builder.startReturn().string("this.").string(child.getName()).end();
857 clazz.add(method); 897 clazz.add(method);
858 } 898 }
859 } 899 }
860 900
861 for (NodeFieldData field : node.getFields()) { 901 for (NodeFieldData field : node.getFields()) {
1105 1145
1106 for (VariableElement var : type.getFields()) { 1146 for (VariableElement var : type.getFields()) {
1107 builder.startStatement(); 1147 builder.startStatement();
1108 String fieldName = var.getSimpleName().toString(); 1148 String fieldName = var.getSimpleName().toString();
1109 1149
1110 CodeTree fieldInit = CodeTreeBuilder.singleString(var.getSimpleName().toString());
1111 builder.string("this.").string(var.getSimpleName().toString());
1112
1113 NodeChildData child = node.findChild(fieldName); 1150 NodeChildData child = node.findChild(fieldName);
1114 if (child != null) { 1151
1115 CreateCastData createCast = node.findCast(child.getName()); 1152 CodeTree init = createStaticCast(builder, child, fieldName);
1116 if (createCast != null) { 1153 init = createAdoptChild(builder, var.asType(), init);
1117 fieldInit = createTemplateMethodCall(builder, null, node.getGenericSpecialization(), createCast, null, child.getName()); 1154
1118 } 1155 builder.string("this.").string(fieldName).string(" = ").tree(init);
1119 }
1120
1121 if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) {
1122 builder.string(" = adoptChild(").tree(fieldInit).string(")");
1123 } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
1124 builder.string(" = adoptChildren(").tree(fieldInit).string(")");
1125 } else {
1126 builder.string(" = ").tree(fieldInit);
1127 }
1128 builder.end(); 1156 builder.end();
1129 } 1157 }
1130 return method; 1158 return method;
1159 }
1160
1161 private CodeTree createStaticCast(CodeTreeBuilder parent, NodeChildData child, String fieldName) {
1162 NodeData parentNode = getModel().getNode();
1163 if (child != null) {
1164 CreateCastData createCast = parentNode.findCast(child.getName());
1165 if (createCast != null) {
1166 return createTemplateMethodCall(parent, null, parentNode.getGenericSpecialization(), createCast, null, fieldName);
1167 }
1168 }
1169 return CodeTreeBuilder.singleString(fieldName);
1170 }
1171
1172 private CodeTree createAdoptChild(CodeTreeBuilder parent, TypeMirror type, CodeTree value) {
1173 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1174 if (Utils.isAssignable(getContext(), type, getContext().getTruffleTypes().getNode())) {
1175 builder.string("adoptChild(").tree(value).string(")");
1176 } else if (Utils.isAssignable(getContext(), type, getContext().getTruffleTypes().getNodeArray())) {
1177 builder.string("adoptChildren(").tree(value).string(")");
1178 } else {
1179 builder.tree(value);
1180 }
1181 return builder.getRoot();
1182 }
1183
1184 private CodeTree createCopyArray(CodeTreeBuilder parent, NodeChildData child, TypeMirror arrayType, CodeBlock<String> accessElement) {
1185 CodeTreeBuilder builder = parent.create();
1186 NodeData node = getModel().getNode();
1187 builder.string("new ").type(arrayType).string(" {");
1188 builder.startCommaGroup();
1189 for (ActualParameter parameter : getModel().getParameters()) {
1190 NodeChildData foundChild = node.findChild(parameter.getSpecification().getName());
1191 if (foundChild == child) {
1192 builder.startGroup();
1193 builder.tree(accessElement.create(builder, String.valueOf(parameter.getIndex())));
1194 builder.end();
1195 }
1196 }
1197 builder.end();
1198 builder.end().string("}");
1199 return builder.getRoot();
1131 } 1200 }
1132 1201
1133 private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor) { 1202 private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
1134 CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); 1203 CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
1135 CodeTreeBuilder builder = method.createBuilder(); 1204 CodeTreeBuilder builder = method.createBuilder();
1139 builder.startStatement().startSuperCall().string("copy").end().end(); 1208 builder.startStatement().startSuperCall().string("copy").end().end();
1140 } 1209 }
1141 1210
1142 for (VariableElement var : type.getFields()) { 1211 for (VariableElement var : type.getFields()) {
1143 builder.startStatement(); 1212 builder.startStatement();
1144 String varName = var.getSimpleName().toString(); 1213 final String varName = var.getSimpleName().toString();
1145 builder.string("this.").string(varName); 1214 final TypeMirror varType = var.asType();
1146 if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) { 1215
1147 builder.string(" = adoptChild(copy.").string(varName).string(")"); 1216 final String copyAccess = "copy." + varName;
1148 } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) { 1217 CodeTree init = CodeTreeBuilder.singleString(copyAccess);
1149 NodeData node = getModel().getNode(); 1218 if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
1150 NodeChildData child = node.findChild(varName); 1219 NodeChildData child = getModel().getNode().findChild(varName);
1151 if (child != null) { 1220 init = createCopyArray(builder, child, varType, new CodeBlock<String>() {
1152 builder.string(" = adoptChildren("); 1221
1153 builder.string("new ").type((child.getNodeType())).string(" {"); 1222 public CodeTree create(CodeTreeBuilder parent, String index) {
1154 builder.startCommaGroup(); 1223 return CodeTreeBuilder.singleString(copyAccess + "[" + index + "]");
1155 for (ActualParameter parameter : getModel().getParameters()) {
1156 NodeChildData foundChild = node.findChild(parameter.getSpecification().getName());
1157 if (foundChild == child) {
1158 builder.startGroup();
1159 builder.string("copy.").string(varName).string("[").string(String.valueOf(parameter.getIndex())).string("]");
1160 builder.end();
1161 }
1162 } 1224 }
1163 1225 });
1164 builder.end().string("})"); 1226 }
1165 } else { 1227 init = createAdoptChild(builder, varType, init);
1166 builder.string(" = adoptChildren(copy.").string(varName).string(")"); 1228 builder.startStatement().string("this.").string(varName).string(" = ").tree(init).end();
1167 }
1168 } else {
1169 builder.string(" = copy.").string(varName);
1170 }
1171 builder.end();
1172 } 1229 }
1173 if (getModel().getNode().isPolymorphic()) { 1230 if (getModel().getNode().isPolymorphic()) {
1174 builder.statement("this.next0 = adoptChild(copy.next0)"); 1231 builder.statement("this.next0 = adoptChild(copy.next0)");
1175 } 1232 }
1176 1233
1182 var.getModifiers().add(Modifier.FINAL); 1239 var.getModifiers().add(Modifier.FINAL);
1183 return var; 1240 return var;
1184 } 1241 }
1185 1242
1186 private CodeVariableElement createChildField(NodeChildData child) { 1243 private CodeVariableElement createChildField(NodeChildData child) {
1187 CodeVariableElement var = new CodeVariableElement(child.getNodeType(), child.getName()); 1244 TypeMirror type = child.getNodeType();
1245 CodeVariableElement var = new CodeVariableElement(type, child.getName());
1188 var.getModifiers().add(Modifier.PROTECTED); 1246 var.getModifiers().add(Modifier.PROTECTED);
1189 1247
1190 DeclaredType annotationType; 1248 DeclaredType annotationType;
1191 if (child.getCardinality() == Cardinality.MANY) { 1249 if (child.getCardinality() == Cardinality.MANY) {
1192 var.getModifiers().add(Modifier.FINAL); 1250 var.getModifiers().add(Modifier.FINAL);
1221 break; 1279 break;
1222 } 1280 }
1223 } 1281 }
1224 1282
1225 builder.startStatement().string("String message = ").startCall("createInfo0").string("reason"); 1283 builder.startStatement().string("String message = ").startCall("createInfo0").string("reason");
1226 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, true); 1284 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, true, null);
1227 builder.end().end(); 1285 builder.end().end();
1228 1286
1229 final String currentNodeVar = currentNode; 1287 final String currentNodeVar = currentNode;
1230 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), rootGroup, true, new CodeBlock<SpecializationData>() { 1288 builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), rootGroup, true, new CodeBlock<SpecializationData>() {
1231 1289
1432 guardsBuilder.string(guardsAnd); 1490 guardsBuilder.string(guardsAnd);
1433 guardsBuilder.tree(implicitGuard); 1491 guardsBuilder.tree(implicitGuard);
1434 guardsAnd = " && "; 1492 guardsAnd = " && ";
1435 } 1493 }
1436 1494
1437 CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType()); 1495 CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType(), minimumState);
1438 if (cast != null) { 1496 if (cast != null) {
1439 castBuilder.tree(cast); 1497 castBuilder.tree(cast);
1440 } 1498 }
1441 } 1499 }
1442 1500
1524 builder.string("("); 1582 builder.string("(");
1525 builder.string("!").string(valueName(shortCircuit)); 1583 builder.string("!").string(valueName(shortCircuit));
1526 builder.string(" || "); 1584 builder.string(" || ");
1527 } 1585 }
1528 1586
1529 startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(targetType)); 1587 String castMethodName;
1588 List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
1589 if (types.size() > 1) {
1590 castMethodName = TypeSystemCodeGenerator.isImplicitTypeMethodName(targetType);
1591 } else {
1592 castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType);
1593 }
1594
1595 startCallTypeSystemMethod(getContext(), builder, node, castMethodName);
1530 builder.string(valueName(source)); 1596 builder.string(valueName(source));
1531 builder.end().end(); // call 1597 builder.end().end(); // call
1532 1598
1533 if (field.isShortCircuit()) { 1599 if (field.isShortCircuit()) {
1534 builder.string(")"); 1600 builder.string(")");
1537 builder.end(); // group 1603 builder.end(); // group
1538 1604
1539 return builder.getRoot(); 1605 return builder.getRoot();
1540 } 1606 }
1541 1607
1542 private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType) { 1608 private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean minimumState) {
1543 NodeData node = field.getNodeData(); 1609 NodeData node = field.getNodeData();
1544 TypeData sourceType = source.getTypeSystemType(); 1610 TypeData sourceType = source.getTypeSystemType();
1545 1611
1546 if (!sourceType.needsCastTo(getContext(), targetType)) { 1612 if (!sourceType.needsCastTo(getContext(), targetType)) {
1547 return null; 1613 return null;
1552 ActualParameter shortCircuit = source.getPreviousParameter(); 1618 ActualParameter shortCircuit = source.getPreviousParameter();
1553 assert shortCircuit != null; 1619 assert shortCircuit != null;
1554 condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); 1620 condition = CodeTreeBuilder.singleString(valueName(shortCircuit));
1555 } 1621 }
1556 1622
1557 CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), CodeTreeBuilder.singleString(valueName(source))); 1623 String castMethodName;
1558 1624 List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
1559 return createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, value); 1625 if (types.size() > 1) {
1626 castMethodName = TypeSystemCodeGenerator.asImplicitTypeMethodName(targetType);
1627 } else {
1628 castMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
1629 }
1630
1631 CodeTree value = createCallTypeSystemMethod(context, parent, node, castMethodName, CodeTreeBuilder.singleString(valueName(source)));
1632
1633 CodeTreeBuilder builder = parent.create();
1634 builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, value));
1635 if (minimumState && types.size() > 1) {
1636 CodeTree castType = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.getImplicitClass(targetType), CodeTreeBuilder.singleString(valueName(source)));
1637 builder.tree(createLazyAssignment(builder, typeName(source), getContext().getType(Class.class), condition, castType));
1638 }
1639
1640 return builder.getRoot();
1560 } 1641 }
1561 1642
1562 private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardData guard) { 1643 private CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardData guard) {
1563 CodeTreeBuilder builder = parent.create(); 1644 CodeTreeBuilder builder = parent.create();
1564 builder.string(prefix); 1645 builder.string(prefix);
1593 builder.end(); 1674 builder.end();
1594 builder.startElseBlock(); 1675 builder.startElseBlock();
1595 builder.tree(createRewriteGeneric(builder, source, current, currentNodeVar)); 1676 builder.tree(createRewriteGeneric(builder, source, current, currentNodeVar));
1596 builder.end(); 1677 builder.end();
1597 } else { 1678 } else {
1598 // simple rewrite
1599 if (current.getExceptions().isEmpty()) { 1679 if (current.getExceptions().isEmpty()) {
1600 builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null), null)); 1680 builder.tree(createGenericInvoke(builder, source, current, createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null), null));
1601 } else { 1681 } else {
1602 builder.startStatement().string(currentNodeVar).string(" = ").tree(createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null)).end(); 1682 builder.startStatement().string(currentNodeVar).string(" = ").tree(createReplaceCall(builder, current, currentNodeVar, currentNodeVar, null)).end();
1603 builder.tree(createGenericInvoke(builder, source, current, null, CodeTreeBuilder.singleString(currentNodeVar))); 1683 builder.tree(createGenericInvoke(builder, source, current, null, CodeTreeBuilder.singleString(currentNodeVar)));
1667 if (replace == null) { 1747 if (replace == null) {
1668 replace = replaceCall; 1748 replace = replaceCall;
1669 } 1749 }
1670 if (current.isGeneric()) { 1750 if (current.isGeneric()) {
1671 builder.startReturn().tree(replace).string(".").startCall(EXECUTE_GENERIC_NAME); 1751 builder.startReturn().tree(replace).string(".").startCall(EXECUTE_GENERIC_NAME);
1672 addInternalValueParameterNames(builder, source, current, null, current.getNode().needsFrame(), true); 1752 addInternalValueParameterNames(builder, source, current, null, current.getNode().needsFrame(), true, null);
1673 builder.end().end(); 1753 builder.end().end();
1674 } else if (current.getMethod() == null) { 1754 } else if (current.getMethod() == null) {
1675 if (replaceCall != null) { 1755 if (replaceCall != null) {
1676 builder.statement(replaceCall); 1756 builder.statement(replaceCall);
1677 } 1757 }
1694 if (target != null) { 1774 if (target != null) {
1695 replaceCall.startCall(target, "replace"); 1775 replaceCall.startCall(target, "replace");
1696 } else { 1776 } else {
1697 replaceCall.startCall("replace"); 1777 replaceCall.startCall("replace");
1698 } 1778 }
1699 replaceCall.startGroup().startNew(className).string(source).end().end(); 1779 replaceCall.startGroup().startNew(className).string(source);
1780 for (ActualParameter param : current.getParameters()) {
1781 if (!param.getSpecification().isSignature()) {
1782 continue;
1783 }
1784 NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
1785 List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
1786 if (types.size() > 1) {
1787 replaceCall.string(typeName(param));
1788 }
1789 }
1790 replaceCall.end().end();
1791
1700 if (message == null) { 1792 if (message == null) {
1701 replaceCall.string("message"); 1793 replaceCall.string("message");
1702 } else { 1794 } else {
1703 replaceCall.doubleQuote(message); 1795 replaceCall.doubleQuote(message);
1704 } 1796 }
1730 builder.startStatement().startCall("polymorphic", "setNext0").string(currentNode).end().end(); 1822 builder.startStatement().startCall("polymorphic", "setNext0").string(currentNode).end().end();
1731 builder.startStatement().startCall(currentNode, "setNext0").startNew(uninitializedName).string(currentNode).end().end().end(); 1823 builder.startStatement().startCall(currentNode, "setNext0").startNew(uninitializedName).string(currentNode).end().end().end();
1732 1824
1733 builder.startReturn(); 1825 builder.startReturn();
1734 builder.startCall(currentNode + ".next0", executeCachedName(node.getGenericPolymorphicSpecialization())); 1826 builder.startCall(currentNode + ".next0", executeCachedName(node.getGenericPolymorphicSpecialization()));
1735 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, true); 1827 addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, true, null);
1736 builder.end(); 1828 builder.end();
1737 builder.end(); 1829 builder.end();
1738 1830
1739 return builder.getRoot(); 1831 return builder.getRoot();
1740 } 1832 }
1774 String[] executeParameterNames = new String[executeParameters.size()]; 1866 String[] executeParameterNames = new String[executeParameters.size()];
1775 for (int i = 0; i < executeParameterNames.length; i++) { 1867 for (int i = 0; i < executeParameterNames.length; i++) {
1776 executeParameterNames[i] = valueName(executeParameters.get(i)); 1868 executeParameterNames[i] = valueName(executeParameters.get(i));
1777 } 1869 }
1778 1870
1779 builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null, true)); 1871 builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null));
1780 1872
1781 CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames); 1873 CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames);
1782 if (needsTry) { 1874 if (needsTry) {
1783 if (!returnVoid) { 1875 if (!returnVoid) {
1784 builder.declaration(primaryType.getPrimitiveType(), "value"); 1876 builder.declaration(primaryType.getPrimitiveType(), "value");
1825 protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, ExecutableTypeData castedType, CodeTree value) { 1917 protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, ExecutableTypeData castedType, CodeTree value) {
1826 boolean hasUnexpected = castedType.hasUnexpectedValue(getContext()); 1918 boolean hasUnexpected = castedType.hasUnexpectedValue(getContext());
1827 return createCastType(node, sourceType, castedType.getType(), hasUnexpected, value); 1919 return createCastType(node, sourceType, castedType.getType(), hasUnexpected, value);
1828 } 1920 }
1829 1921
1830 protected CodeTree createCastType(NodeData node, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) {
1831 if (targetType == null) {
1832 return value;
1833 } else if (!sourceType.needsCastTo(getContext(), targetType)) {
1834 return value;
1835 }
1836
1837 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
1838 String targetMethodName;
1839 if (expect) {
1840 targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType);
1841 } else {
1842 targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType);
1843 }
1844 startCallTypeSystemMethod(getContext(), builder, node, targetMethodName);
1845
1846 builder.tree(value);
1847 builder.end().end();
1848 return builder.getRoot();
1849 }
1850
1851 protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters, 1922 protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters,
1852 ActualParameter unexpectedParameter, boolean cast) { 1923 ActualParameter unexpectedParameter) {
1853 NodeData sourceNode = specialization.getNode(); 1924 CodeTreeBuilder builder = parent.create();
1854 1925 NodeData node = specialization.getNode();
1855 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1856
1857 for (ActualParameter targetParameter : targetParameters) { 1926 for (ActualParameter targetParameter : targetParameters) {
1858 NodeChildData field = sourceNode.findChild(targetParameter.getSpecification().getName()); 1927 NodeChildData child = node.findChild(targetParameter.getSpecification().getName());
1859 if (!targetParameter.getSpecification().isSignature()) { 1928 if (!targetParameter.getSpecification().isSignature()) {
1860 continue; 1929 continue;
1861 } 1930 }
1862
1863 TypeData targetType = targetParameter.getTypeSystemType(); 1931 TypeData targetType = targetParameter.getTypeSystemType();
1864 ExecutableTypeData targetExecutable = null; 1932 ExecutableTypeData targetExecutable = null;
1865 if (field != null) { 1933 if (child != null) {
1866 targetExecutable = field.findExecutableType(getContext(), targetType); 1934 targetExecutable = child.findExecutableType(getContext(), targetType);
1867 } 1935 }
1868 1936
1869 ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); 1937 if (targetExecutable == null) {
1870 1938 // TODO what to do? assertion?
1871 String targetVariableName = valueName(targetParameter); 1939 continue;
1872 1940 }
1873 CodeTree executionExpression = null; 1941
1874 if ((sourceParameter != null && cast) || sourceParameter != null) { 1942 CodeTree executionExpressions = createExecutionExpresssions(builder, child, sourceExecutable, targetExecutable, targetParameter, unexpectedParameter);
1875 TypeData sourceType = sourceParameter.getTypeSystemType(); 1943
1876 if (targetExecutable == null || !sourceType.needsCastTo(getContext(), targetType)) { 1944 String targetVarName = valueName(targetParameter);
1877 if (field != null && field.isShortCircuit() && sourceParameter != null) { 1945 CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, targetVarName, specialization, sourceExecutable, targetExecutable, targetParameter,
1878 builder.tree(createShortCircuitValue(builder, specialization, field, targetParameter.getPreviousParameter(), unexpectedParameter)); 1946 isShortCircuit(child));
1879 } 1947 CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, targetVarName, specialization, targetParameter, unexpectedParameter);
1880 builder.startStatement(); 1948
1881 builder.type(targetParameter.getType()).string(" "); 1949 if (shortCircuitTree == executionExpressions) {
1882 builder.string(targetVariableName).string(" = "); 1950 if (containsNewLine(executionExpressions)) {
1883 builder.tree(CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter))); 1951 builder.declaration(sourceExecutable.getType().getPrimitiveType(), targetVarName);
1952 builder.tree(shortCircuitTree);
1953 } else {
1954 builder.startStatement().type(targetParameter.getType()).string(" ").tree(shortCircuitTree).end();
1955 }
1956 } else {
1957 builder.tree(shortCircuitTree);
1958 }
1959
1960 }
1961 return builder.getRoot();
1962 }
1963
1964 private CodeTree createExecutionExpresssions(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ExecutableTypeData targetExecutable, ActualParameter param,
1965 ActualParameter unexpectedParameter) {
1966 CodeTreeBuilder builder = parent.create();
1967
1968 TypeData type = param.getTypeSystemType();
1969 List<TypeData> targetTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(type);
1970
1971 if (targetTypes.size() > 1) {
1972 boolean elseIf = false;
1973 int index = 0;
1974 for (TypeData typeData : targetTypes) {
1975 if (index < targetTypes.size() - 1) {
1976 elseIf = builder.startIf(elseIf);
1977 builder.string(typeName(param)).string(" == ").typeLiteral(typeData.getPrimitiveType());
1884 builder.end(); 1978 builder.end();
1885 continue; 1979 builder.startBlock();
1886 } else { 1980 } else {
1887 CodeTree valueTree = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)); 1981 builder.startElseBlock();
1888 executionExpression = createExpectExecutableType(sourceNode, sourceType, targetExecutable, valueTree); 1982 }
1889 } 1983
1890 } else if (sourceParameter == null) { 1984 ExecutableTypeData implictExecutableTypeData = child.getNodeData().findExecutableType(typeData, targetExecutable.getEvaluatedCount());
1891 executionExpression = createExecuteChildExpression(builder, field, targetParameter, unexpectedParameter); 1985 ImplicitCastData cast = child.getNodeData().getTypeSystem().lookupCast(typeData, param.getTypeSystemType());
1892 } 1986 CodeTree execute = createExecuteExpression(parent, child, sourceExecutable, implictExecutableTypeData, param, unexpectedParameter, cast);
1893 1987 builder.statement(execute);
1894 if (executionExpression != null) { 1988 builder.end();
1895 CodeTreeVariable executionVar = new CodeTreeVariable(); 1989 index++;
1896 CodeTree shortCircuitTree = createShortCircuitTree(builder, executionVar, targetVariableName, specialization, targetParameter, unexpectedParameter); 1990 }
1897 CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpression, targetVariableName, specialization, sourceExecutable, targetExecutable, targetParameter, 1991 } else {
1898 shortCircuitTree != executionVar); 1992 builder.tree(createExecuteExpression(parent, child, sourceExecutable, targetExecutable, param, unexpectedParameter, null));
1899
1900 executionVar.set(unexpectedTree);
1901 builder.tree(shortCircuitTree);
1902 }
1903 } 1993 }
1904 return builder.getRoot(); 1994 return builder.getRoot();
1995 }
1996
1997 private CodeTree createExecuteExpression(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ExecutableTypeData targetExecutable,
1998 ActualParameter targetParameter, ActualParameter unexpectedParameter, ImplicitCastData cast) {
1999 CodeTreeBuilder builder = parent.create();
2000 builder.string(valueName(targetParameter));
2001 builder.string(" = ");
2002 if (cast != null) {
2003 startCallTypeSystemMethod(getContext(), builder, child.getNodeData(), cast.getMethodName());
2004 }
2005
2006 NodeData node = getModel().getNode();
2007 ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName());
2008 if (sourceParameter == null) {
2009 builder.tree(createExecuteChildExpression(builder, child, targetParameter, targetExecutable, unexpectedParameter));
2010 } else {
2011 CodeTree var = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter));
2012 builder.tree(createExpectExecutableType(node, sourceParameter.getTypeSystemType(), targetExecutable, var));
2013 }
2014 if (cast != null) {
2015 builder.end().end();
2016 }
2017
2018 return builder.getRoot();
2019 }
2020
2021 private boolean containsNewLine(CodeTree tree) {
2022 if (tree.getCodeKind() == CodeTreeKind.NEW_LINE) {
2023 return true;
2024 }
2025
2026 for (CodeTree codeTree : tree.getEnclosedElements()) {
2027 if (containsNewLine(codeTree)) {
2028 return true;
2029 }
2030 }
2031 return false;
2032 }
2033
2034 private boolean hasUnexpected(ExecutableTypeData target, ActualParameter sourceParameter, ActualParameter targetParameter) {
2035 List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType());
2036 NodeChildData child = getModel().getNode().findChild(targetParameter.getSpecification().getName());
2037 boolean hasUnexpected = false;
2038 for (TypeData type : types) {
2039 if (hasUnexpected) {
2040 continue;
2041 }
2042 ExecutableTypeData execTarget = target;
2043 if (type != execTarget.getType()) {
2044 execTarget = child.findExecutableType(getContext(), type);
2045 }
2046 hasUnexpected = hasUnexpected || hasUnexpectedType(execTarget, sourceParameter, type);
2047 }
2048 return hasUnexpected;
2049 }
2050
2051 private boolean hasUnexpectedType(ExecutableTypeData target, ActualParameter sourceParameter, TypeData type) {
2052 if (sourceParameter == null) {
2053 return target.hasUnexpectedValue(getContext());
2054 } else {
2055 if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), type)) {
2056 return target.hasUnexpectedValue(getContext());
2057 }
2058 return false;
2059 }
1905 } 2060 }
1906 2061
1907 private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ExecutableTypeData currentExecutable, 2062 private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ExecutableTypeData currentExecutable,
1908 ExecutableTypeData targetExecutable, ActualParameter param, boolean shortCircuit) { 2063 ExecutableTypeData targetExecutable, ActualParameter param, boolean shortCircuit) {
1909 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 2064 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1910 boolean unexpected = targetExecutable.hasUnexpectedValue(getContext()); 2065 ActualParameter sourceParameter = currentExecutable.findParameter(param.getLocalName());
1911 boolean cast = false; 2066 boolean unexpected = hasUnexpected(targetExecutable, sourceParameter, param);
1912 if (targetExecutable.getType().needsCastTo(getContext(), param.getTypeSystemType())) { 2067 if (!unexpected) {
1913 unexpected = true; 2068 return body;
1914 cast = true; 2069 }
1915 }
1916
1917 builder.startStatement();
1918 2070
1919 if (!shortCircuit) { 2071 if (!shortCircuit) {
1920 builder.type(param.getType()).string(" ").string(targetVariableName); 2072 builder.declaration(param.getType(), targetVariableName);
1921 } 2073 }
1922 2074 builder.startTryBlock();
1923 if (unexpected) { 2075
1924 if (!shortCircuit) { 2076 if (containsNewLine(body)) {
1925 builder.end();
1926 }
1927 builder.startTryBlock();
1928 builder.startStatement();
1929 builder.string(targetVariableName);
1930 } else if (shortCircuit) {
1931 builder.startStatement();
1932 builder.string(targetVariableName);
1933 }
1934 builder.string(" = ");
1935 if (cast) {
1936 builder.tree(createCastType(specialization.getNode(), targetExecutable.getType(), param.getTypeSystemType(), true, body));
1937 } else {
1938 builder.tree(body); 2077 builder.tree(body);
1939 } 2078 } else {
1940 builder.end(); 2079 builder.statement(body);
1941 2080 }
1942 if (unexpected) { 2081
1943 builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); 2082 builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
1944 SpecializationData generic = specialization.getNode().getGenericSpecialization(); 2083 SpecializationData generic = specialization.getNode().getGenericSpecialization();
1945 ActualParameter genericParameter = generic.findParameter(param.getLocalName()); 2084 ActualParameter genericParameter = generic.findParameter(param.getLocalName());
1946 2085
1947 List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter); 2086 List<ActualParameter> genericParameters = generic.getParametersAfter(genericParameter);
1948 builder.tree(createDeoptimize(builder)); 2087 builder.tree(createDeoptimize(builder));
1949 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false)); 2088 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter));
1950 if (specialization.isPolymorphic()) { 2089 if (specialization.isPolymorphic()) {
1951 builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param)); 2090 builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param));
1952 } else { 2091 } else {
1953 builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization, param, 2092 builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization, param,
1954 "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType()))); 2093 "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType())));
1955 } 2094 }
1956 builder.end(); // catch block 2095 builder.end(); // catch block
1957 }
1958 2096
1959 return builder.getRoot(); 2097 return builder.getRoot();
1960 } 2098 }
1961 2099
1962 private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, ActualParameter param) { 2100 private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, ActualParameter param) {
1967 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 2105 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1968 builder.startReturn(); 2106 builder.startReturn();
1969 2107
1970 CodeTreeBuilder execute = new CodeTreeBuilder(builder); 2108 CodeTreeBuilder execute = new CodeTreeBuilder(builder);
1971 execute.startCall("next0", executeCachedName(generic)); 2109 execute.startCall("next0", executeCachedName(generic));
1972 addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true); 2110 addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true, null);
1973 execute.end(); 2111 execute.end();
1974 2112
1975 TypeData sourceType = generic.getReturnType().getTypeSystemType(); 2113 TypeData sourceType = generic.getReturnType().getTypeSystemType();
1976 2114
1977 builder.tree(createExpectExecutableType(node, sourceType, currentExecutable, execute.getRoot())); 2115 builder.tree(createExpectExecutableType(node, sourceType, currentExecutable, execute.getRoot()));
1978 2116
1979 builder.end(); 2117 builder.end();
1980 return builder.getRoot(); 2118 return builder.getRoot();
1981 } 2119 }
1982 2120
1983 private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetField, ActualParameter sourceParameter, ActualParameter unexpectedParameter) { 2121 private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetChild, ActualParameter targetParameter, ExecutableTypeData targetExecutable,
1984 TypeData type = sourceParameter.getTypeSystemType(); 2122 ActualParameter unexpectedParameter) {
1985 ExecutableTypeData execType = targetField.findExecutableType(getContext(), type);
1986
1987 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 2123 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
1988 if (targetField != null) { 2124 if (targetChild != null) {
1989 Element accessElement = targetField.getAccessElement(); 2125 builder.tree(createAccessChild(builder, targetChild, targetParameter));
1990 if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) {
1991 builder.string("this.").string(targetField.getName());
1992 } else if (accessElement.getKind() == ElementKind.FIELD) {
1993 builder.string("this.").string(accessElement.getSimpleName().toString());
1994 } else {
1995 throw new AssertionError();
1996 }
1997 if (sourceParameter.getSpecification().isIndexed()) {
1998 builder.string("[" + sourceParameter.getIndex() + "]");
1999 }
2000 builder.string("."); 2126 builder.string(".");
2001 } 2127 }
2002 2128
2003 builder.startCall(execType.getMethodName()); 2129 builder.startCall(targetExecutable.getMethodName());
2004 2130
2131 // TODO this should be merged with #createTemplateMethodCall
2005 int index = 0; 2132 int index = 0;
2006 for (ActualParameter parameter : execType.getParameters()) { 2133 for (ActualParameter parameter : targetExecutable.getParameters()) {
2007 2134
2008 if (!parameter.getSpecification().isSignature()) { 2135 if (!parameter.getSpecification().isSignature()) {
2009 builder.string(parameter.getLocalName()); 2136 builder.string(parameter.getLocalName());
2010 } else { 2137 } else {
2011 2138
2012 if (index < targetField.getExecuteWith().size()) { 2139 if (index < targetChild.getExecuteWith().size()) {
2013 NodeChildData child = targetField.getExecuteWith().get(index); 2140 NodeChildData child = targetChild.getExecuteWith().get(index);
2014 2141
2015 ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName()); 2142 ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName());
2016 List<ActualParameter> specializationParams = getModel().findParameters(spec); 2143 List<ActualParameter> specializationParams = getModel().findParameters(spec);
2017 2144
2018 if (specializationParams.isEmpty()) { 2145 if (specializationParams.isEmpty()) {
2047 builder.end(); 2174 builder.end();
2048 2175
2049 return builder.getRoot(); 2176 return builder.getRoot();
2050 } 2177 }
2051 2178
2179 private CodeTree createAccessChild(CodeTreeBuilder parent, NodeChildData targetChild, ActualParameter targetParameter) throws AssertionError {
2180 CodeTreeBuilder builder = parent.create();
2181 Element accessElement = targetChild.getAccessElement();
2182 if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) {
2183 builder.string("this.").string(targetChild.getName());
2184 } else if (accessElement.getKind() == ElementKind.FIELD) {
2185 builder.string("this.").string(accessElement.getSimpleName().toString());
2186 } else {
2187 throw new AssertionError();
2188 }
2189 if (targetParameter.getSpecification().isIndexed()) {
2190 builder.string("[" + targetParameter.getIndex() + "]");
2191 }
2192 return builder.getRoot();
2193 }
2194
2052 private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ActualParameter parameter, 2195 private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ActualParameter parameter,
2053 ActualParameter exceptionParam) { 2196 ActualParameter exceptionParam) {
2197 NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName());
2198 if (!isShortCircuit(forField)) {
2199 return body;
2200 }
2201
2054 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 2202 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2055
2056 NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName());
2057 if (forField == null) {
2058 return body;
2059 }
2060
2061 if (forField.getExecutionKind() != ExecutionKind.SHORT_CIRCUIT) {
2062 return body;
2063 }
2064
2065 ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter); 2203 ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter);
2066
2067 builder.tree(createShortCircuitValue(builder, specialization, forField, shortCircuitParam, exceptionParam)); 2204 builder.tree(createShortCircuitValue(builder, specialization, forField, shortCircuitParam, exceptionParam));
2068
2069 builder.declaration(parameter.getType(), targetVariableName, CodeTreeBuilder.createBuilder().defaultValue(parameter.getType())); 2205 builder.declaration(parameter.getType(), targetVariableName, CodeTreeBuilder.createBuilder().defaultValue(parameter.getType()));
2070 builder.startIf().string(shortCircuitParam.getLocalName()).end(); 2206 builder.startIf().string(shortCircuitParam.getLocalName()).end();
2071 builder.startBlock(); 2207 builder.startBlock();
2072 builder.tree(body); 2208
2209 if (containsNewLine(body)) {
2210 builder.tree(body);
2211 } else {
2212 builder.statement(body);
2213 }
2073 builder.end(); 2214 builder.end();
2074 2215
2075 return builder.getRoot(); 2216 return builder.getRoot();
2217 }
2218
2219 private boolean isShortCircuit(NodeChildData forField) {
2220 return forField != null && forField.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT;
2076 } 2221 }
2077 2222
2078 private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeChildData forField, ActualParameter shortCircuitParam, ActualParameter exceptionParam) { 2223 private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeChildData forField, ActualParameter shortCircuitParam, ActualParameter exceptionParam) {
2079 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 2224 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2080 int shortCircuitIndex = 0; 2225 int shortCircuitIndex = 0;
2107 NodeData node = current.getNode(); 2252 NodeData node = current.getNode();
2108 SpecializationData generic = node.getGenericSpecialization(); 2253 SpecializationData generic = node.getGenericSpecialization();
2109 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); 2254 CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
2110 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); 2255 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);
2111 specializeCall.string(String.valueOf(node.getSpecializations().indexOf(current))); 2256 specializeCall.string(String.valueOf(node.getSpecializations().indexOf(current)));
2112 addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true); 2257 addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true, null);
2113 specializeCall.doubleQuote(reason); 2258 specializeCall.doubleQuote(reason);
2114 specializeCall.end().end(); 2259 specializeCall.end().end();
2115 2260
2116 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 2261 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2117 2262
2195 builder.end().end(); // call 2340 builder.end().end(); // call
2196 builder.end(); 2341 builder.end();
2197 } 2342 }
2198 return method; 2343 return method;
2199 } 2344 }
2345 }
2346
2347 private class BaseCastNodeFactory extends ClassElementFactory<NodeData> {
2348
2349 protected final Set<TypeData> usedTargetTypes;
2350
2351 public BaseCastNodeFactory(ProcessorContext context, Set<TypeData> usedTargetTypes) {
2352 super(context);
2353 this.usedTargetTypes = usedTargetTypes;
2354 }
2355
2356 @Override
2357 protected CodeTypeElement create(NodeData m) {
2358 CodeTypeElement type = createClass(m, modifiers(STATIC), nodeCastClassName(m, null), context.getTruffleTypes().getNode(), false);
2359
2360 CodeVariableElement delegate = new CodeVariableElement(m.getNodeType(), "delegate");
2361 delegate.getModifiers().add(PROTECTED);
2362 delegate.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation()));
2363
2364 type.add(delegate);
2365 type.add(createConstructorUsingFields(modifiers(), type));
2366 return type;
2367 }
2368
2369 @Override
2370 protected void createChildren(NodeData m) {
2371 CodeTypeElement type = getElement();
2372 type.add(createExecute(EXECUTE_SPECIALIZE_NAME, true));
2373 type.add(createExecute(EXECUTE_GENERIC_NAME, false));
2374
2375 for (ExecutableTypeData targetExecutable : m.getExecutableTypes()) {
2376 if (!usedTargetTypes.contains(targetExecutable.getType()) && targetExecutable.hasUnexpectedValue(getContext())) {
2377 continue;
2378 }
2379 CodeExecutableElement execute = createCastExecute(targetExecutable, targetExecutable, false);
2380 CodeExecutableElement expect = createCastExecute(targetExecutable, targetExecutable, true);
2381 if (execute != null) {
2382 getElement().add(execute);
2383 }
2384 if (expect != null) {
2385 getElement().add(expect);
2386 }
2387 }
2388 Set<TypeData> sourceTypes = new TreeSet<>();
2389 List<ImplicitCastData> casts = getModel().getTypeSystem().getImplicitCasts();
2390 for (ImplicitCastData cast : casts) {
2391 sourceTypes.add(cast.getSourceType());
2392 }
2393
2394 CodeTypeElement baseType = getElement();
2395 for (TypeData sourceType : sourceTypes) {
2396 add(new SpecializedCastNodeFactory(context, baseType, sourceType, usedTargetTypes), getModel());
2397 }
2398 }
2399
2400 private CodeExecutableElement createExecute(String name, boolean specialize) {
2401 NodeData node = getModel();
2402 TypeMirror objectType = node.getTypeSystem().getGenericType();
2403 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), objectType, name, new CodeVariableElement(objectType, "value"));
2404 if (specialize) {
2405 method.getModifiers().add(FINAL);
2406 }
2407 CodeTreeBuilder builder = method.createBuilder();
2408
2409 List<ImplicitCastData> casts = node.getTypeSystem().getImplicitCasts();
2410 boolean elseIf = false;
2411 for (ImplicitCastData cast : casts) {
2412 elseIf = builder.startIf(elseIf);
2413 startCallTypeSystemMethod(context, builder, getModel(), TypeSystemCodeGenerator.isTypeMethodName(cast.getSourceType()));
2414 builder.string("value");
2415 builder.end().end();
2416 builder.end();
2417 builder.startBlock();
2418
2419 if (specialize) {
2420 builder.startStatement().startCall("replace").startNew(nodeCastClassName(getModel(), cast.getSourceType())).string("delegate").end().doubleQuote("Added cast").end().end();
2421 }
2422 builder.startReturn();
2423
2424 startCallTypeSystemMethod(context, builder, getModel(), cast.getMethodName());
2425 startCallTypeSystemMethod(context, builder, getModel(), TypeSystemCodeGenerator.asTypeMethodName(cast.getSourceType()));
2426 builder.string("value");
2427 builder.end().end();
2428 builder.end().end();
2429
2430 builder.end();
2431 builder.end();
2432 }
2433
2434 builder.startReturn().string("value").end();
2435
2436 return method;
2437 }
2438
2439 protected CodeExecutableElement createCastExecute(ExecutableTypeData sourceExecutable, ExecutableTypeData targetExecutable, boolean expect) {
2440 ImplicitCastData cast = null;
2441 if (!sourceExecutable.getType().equals(targetExecutable.getType())) {
2442 cast = getModel().getTypeSystem().lookupCast(sourceExecutable.getType(), targetExecutable.getType());
2443 if (cast == null) {
2444 return null;
2445 }
2446 }
2447
2448 if (expect) {
2449 if (targetExecutable.getEvaluatedCount() > 0) {
2450 return null;
2451 } else if (Utils.isObject(targetExecutable.getType().getPrimitiveType())) {
2452 return null;
2453 }
2454 }
2455
2456 boolean hasTargetUnexpected = targetExecutable.hasUnexpectedValue(getContext());
2457 boolean hasSourceUnexpected = sourceExecutable.hasUnexpectedValue(getContext());
2458
2459 CodeExecutableElement method = copyTemplateMethod(targetExecutable);
2460 method.getModifiers().add(PUBLIC);
2461
2462 CodeTreeBuilder builder = method.createBuilder();
2463
2464 if (hasSourceUnexpected && cast != null) {
2465 builder.startTryBlock();
2466 }
2467
2468 if (expect) {
2469 method.getParameters().clear();
2470 String expectMethodName;
2471 if (hasTargetUnexpected) {
2472 expectMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetExecutable.getType());
2473 } else {
2474 expectMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetExecutable.getType());
2475 }
2476 method.setSimpleName(CodeNames.of(expectMethodName));
2477 method.addParameter(new CodeVariableElement(getModel().getTypeSystem().getGenericType(), "value"));
2478 }
2479
2480 builder.startReturn();
2481 CodeTree executeCall;
2482 if (expect) {
2483 executeCall = createCastType(getModel(), getModel().getTypeSystem().getGenericTypeData(), sourceExecutable.getType(), hasSourceUnexpected, CodeTreeBuilder.singleString("value"));
2484 } else {
2485 executeCall = createTemplateMethodCall(builder, CodeTreeBuilder.singleString("delegate."), targetExecutable, sourceExecutable, null);
2486 }
2487 if (cast != null) {
2488 startCallTypeSystemMethod(context, builder, getModel(), cast.getMethodName());
2489 builder.tree(executeCall);
2490 builder.end().end();
2491 } else {
2492 builder.tree(executeCall);
2493 }
2494 builder.end();
2495
2496 if (hasSourceUnexpected && cast != null) {
2497 builder.end();
2498 builder.startCatchBlock(getContext().getTruffleTypes().getUnexpectedValueException(), "ex");
2499 builder.startStatement().startCall("replace").startNew(nodeCastClassName(getModel(), null)).string("delegate").end().doubleQuote("Removed cast").end().end();
2500
2501 if (hasTargetUnexpected) {
2502 builder.startThrow().string("ex").end();
2503 } else {
2504 builder.startThrow().startNew(getContext().getType(AssertionError.class)).end().end();
2505 }
2506 builder.end();
2507 }
2508
2509 return method;
2510 }
2511
2512 private CodeExecutableElement copyTemplateMethod(TemplateMethod targetExecutable) {
2513 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), targetExecutable.getMethod());
2514 method.getModifiers().remove(ABSTRACT);
2515 method.getAnnotationMirrors().clear();
2516 Modifier visibility = Utils.getVisibility(method.getModifiers());
2517 if (visibility != null) {
2518 method.getModifiers().remove(visibility);
2519 }
2520 int index = 0;
2521 for (ActualParameter parameter : targetExecutable.getParameters()) {
2522 ((CodeVariableElement) method.getParameters().get(index)).setName(parameter.getLocalName());
2523 index++;
2524 }
2525 return method;
2526 }
2527
2528 }
2529
2530 private class SpecializedCastNodeFactory extends BaseCastNodeFactory {
2531
2532 private final CodeTypeElement baseType;
2533 private final TypeData sourceType;
2534
2535 public SpecializedCastNodeFactory(ProcessorContext context, CodeTypeElement baseType, TypeData type, Set<TypeData> usedTargetTypes) {
2536 super(context, usedTargetTypes);
2537 this.baseType = baseType;
2538 this.sourceType = type;
2539 }
2540
2541 @Override
2542 protected CodeTypeElement create(NodeData m) {
2543 CodeTypeElement type = createClass(m, modifiers(PRIVATE, STATIC, FINAL), nodeCastClassName(m, sourceType), baseType.asType(), false);
2544 type.add(createConstructorUsingFields(modifiers(), type));
2545 return type;
2546 }
2547
2548 @Override
2549 protected void createChildren(NodeData node) {
2550 for (TypeData targetType : usedTargetTypes) {
2551 for (ExecutableTypeData targetExecutable : node.getExecutableTypes()) {
2552 if (targetExecutable.getType().equals(targetType)) {
2553 ExecutableTypeData sourceExecutable = node.findExecutableType(sourceType, targetExecutable.getEvaluatedCount());
2554 if (sourceExecutable == null) {
2555 // TODO what if there is no evaluated version?
2556 continue;
2557 }
2558 CodeExecutableElement execute = createCastExecute(sourceExecutable, targetExecutable, false);
2559 CodeExecutableElement expect = createCastExecute(sourceExecutable, targetExecutable, true);
2560 if (execute != null) {
2561 getElement().add(execute);
2562 }
2563 if (expect != null) {
2564 getElement().add(expect);
2565 }
2566 }
2567 }
2568
2569 }
2570 }
2571
2200 } 2572 }
2201 2573
2202 private class SpecializedNodeFactory extends NodeBaseFactory { 2574 private class SpecializedNodeFactory extends NodeBaseFactory {
2203 2575
2204 protected final CodeTypeElement nodeGen; 2576 protected final CodeTypeElement nodeGen;
2275 continue; 2647 continue;
2276 } 2648 }
2277 } 2649 }
2278 2650
2279 CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor); 2651 CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor);
2652 CodeTree body = superConstructor.getBodyTree();
2653 CodeTreeBuilder builder = superConstructor.createBuilder();
2654 builder.tree(body);
2280 2655
2281 if (superConstructor != null) { 2656 if (superConstructor != null) {
2282 if (getModel().isGeneric() && node.isPolymorphic()) { 2657 if (getModel().isGeneric() && node.isPolymorphic()) {
2283 CodeTree body = superConstructor.getBodyTree();
2284 CodeTreeBuilder builder = superConstructor.createBuilder();
2285 builder.tree(body);
2286 builder.statement("this.next0 = null"); 2658 builder.statement("this.next0 = null");
2659 }
2660
2661 for (ActualParameter param : getModel().getParameters()) {
2662 if (!param.getSpecification().isSignature()) {
2663 continue;
2664 }
2665 NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
2666 List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
2667 if (types.size() > 1) {
2668 clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), typeName(param)));
2669 superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), typeName(param)));
2670
2671 builder.startStatement();
2672 builder.string("this.").string(typeName(param)).string(" = ").string(typeName(param));
2673 builder.end();
2674 }
2287 } 2675 }
2288 2676
2289 clazz.add(superConstructor); 2677 clazz.add(superConstructor);
2290 } 2678 }
2291 } 2679 }
2331 } else if (specialization.isUninitialized()) { 2719 } else if (specialization.isUninitialized()) {
2332 builder.tree(createAppendPolymorphic(builder, specialization)); 2720 builder.tree(createAppendPolymorphic(builder, specialization));
2333 } else { 2721 } else {
2334 CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); 2722 CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder);
2335 elseBuilder.startReturn().startCall("this.next0", executeCachedName(polymorphic)); 2723 elseBuilder.startReturn().startCall("this.next0", executeCachedName(polymorphic));
2336 addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true); 2724 addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true, null);
2337 elseBuilder.end().end(); 2725 elseBuilder.end().end();
2338 2726
2339 boolean forceElse = specialization.getExceptions().size() > 0; 2727 boolean forceElse = specialization.getExceptions().size() > 0;
2340 builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() { 2728 builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), false, new CodeBlock<SpecializationData>() {
2341 2729
2373 builder.end().end(); 2761 builder.end().end();
2374 2762
2375 CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder); 2763 CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder);
2376 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); 2764 specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);
2377 specializeCall.string("0"); 2765 specializeCall.string("0");
2378 addInternalValueParameterNames(specializeCall, specialization, node.getGenericSpecialization(), null, true, true); 2766 addInternalValueParameterNames(specializeCall, specialization, node.getGenericSpecialization(), null, true, true, null);
2379 specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end(); 2767 specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end();
2380 specializeCall.end().end(); 2768 specializeCall.end().end();
2381 2769
2382 builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot()); 2770 builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot());
2383 2771
2480 CodeTreeBuilder builder = new CodeTreeBuilder(parent); 2868 CodeTreeBuilder builder = new CodeTreeBuilder(parent);
2481 if (specialization.isUninitialized()) { 2869 if (specialization.isUninitialized()) {
2482 builder.tree(createDeoptimize(builder)); 2870 builder.tree(createDeoptimize(builder));
2483 } 2871 }
2484 2872
2485 builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null, false)); 2873 builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null));
2486 2874
2487 CodeTree returnSpecialized = null; 2875 CodeTree returnSpecialized = null;
2488 2876
2489 if (specialization.findNextSpecialization() != null) { 2877 if (specialization.findNextSpecialization() != null) {
2490 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder); 2878 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder);
2517 } 2905 }
2518 2906
2519 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); 2907 CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent);
2520 if (specialization.isPolymorphic()) { 2908 if (specialization.isPolymorphic()) {
2521 returnBuilder.startCall("next0", executeCachedName(specialization)); 2909 returnBuilder.startCall("next0", executeCachedName(specialization));
2522 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true); 2910 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true, null);
2523 returnBuilder.end(); 2911 returnBuilder.end();
2524 } else if (specialization.isUninitialized()) { 2912 } else if (specialization.isUninitialized()) {
2525 returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME); 2913 returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME);
2526 returnBuilder.string("0"); 2914 returnBuilder.string("0");
2527 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true); 2915 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true, null);
2528 returnBuilder.doubleQuote("Uninitialized monomorphic"); 2916 returnBuilder.doubleQuote("Uninitialized monomorphic");
2529 returnBuilder.end(); 2917 returnBuilder.end();
2530 } else if (specialization.getMethod() == null && !node.needsRewrites(context)) { 2918 } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
2531 emitEncounteredSynthetic(builder, specialization); 2919 emitEncounteredSynthetic(builder, specialization);
2532 } else if (specialization.isGeneric()) { 2920 } else if (specialization.isGeneric()) {
2533 returnBuilder.startCall("super", EXECUTE_GENERIC_NAME); 2921 returnBuilder.startCall("super", EXECUTE_GENERIC_NAME);
2534 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, node.needsFrame(), true); 2922 addInternalValueParameterNames(returnBuilder, specialization, specialization, null, node.needsFrame(), true, null);
2535 returnBuilder.end(); 2923 returnBuilder.end();
2536 } else { 2924 } else {
2537 returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null)); 2925 returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null));
2538 } 2926 }
2539 2927
2540 if (!returnBuilder.isEmpty()) { 2928 if (!returnBuilder.isEmpty()) {
2541
2542 ExecutableTypeData sourceExecutableType = node.findExecutableType(specialization.getReturnType().getTypeSystemType(), 0); 2929 ExecutableTypeData sourceExecutableType = node.findExecutableType(specialization.getReturnType().getTypeSystemType(), 0);
2543 boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext()); 2930 boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext());
2544 boolean targetSupportsUnexpected = executable.hasUnexpectedValue(getContext()); 2931 boolean targetSupportsUnexpected = executable.hasUnexpectedValue(getContext());
2545 2932
2546 TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType()); 2933 TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType());