Mercurial > hg > truffle
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()); |