Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java @ 20940:476374f3fe9a
Truffle-DSL: generate better polymorphic execute signatures
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Tue, 14 Apr 2015 15:12:48 +0200 |
parents | 18c0f02fa4d2 |
children | 4f45e4d3361c |
comparison
equal
deleted
inserted
replaced
20939:f83fd99b2962 | 20940:476374f3fe9a |
---|---|
31 import javax.tools.Diagnostic.Kind; | 31 import javax.tools.Diagnostic.Kind; |
32 | 32 |
33 import com.oracle.truffle.api.*; | 33 import com.oracle.truffle.api.*; |
34 import com.oracle.truffle.api.dsl.*; | 34 import com.oracle.truffle.api.dsl.*; |
35 import com.oracle.truffle.api.dsl.internal.*; | 35 import com.oracle.truffle.api.dsl.internal.*; |
36 import com.oracle.truffle.api.frame.*; | |
36 import com.oracle.truffle.api.nodes.*; | 37 import com.oracle.truffle.api.nodes.*; |
37 import com.oracle.truffle.dsl.processor.*; | 38 import com.oracle.truffle.dsl.processor.*; |
38 import com.oracle.truffle.dsl.processor.expression.*; | 39 import com.oracle.truffle.dsl.processor.expression.*; |
39 import com.oracle.truffle.dsl.processor.java.*; | 40 import com.oracle.truffle.dsl.processor.java.*; |
40 import com.oracle.truffle.dsl.processor.java.compiler.*; | 41 import com.oracle.truffle.dsl.processor.java.compiler.*; |
41 import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror; | 42 import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror; |
42 import com.oracle.truffle.dsl.processor.java.model.*; | 43 import com.oracle.truffle.dsl.processor.java.model.*; |
43 import com.oracle.truffle.dsl.processor.model.*; | 44 import com.oracle.truffle.dsl.processor.model.*; |
44 import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality; | 45 import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality; |
45 import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind; | 46 import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind; |
46 import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature; | |
47 | 47 |
48 @DSLOptions | 48 @DSLOptions |
49 public class NodeParser extends AbstractParser<NodeData> { | 49 public class NodeParser extends AbstractParser<NodeData> { |
50 | 50 |
51 public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Fallback.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class, | 51 public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Fallback.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class, |
102 try { | 102 try { |
103 node = parseNode(rootType); | 103 node = parseNode(rootType); |
104 } catch (CompileErrorException e) { | 104 } catch (CompileErrorException e) { |
105 throw e; | 105 throw e; |
106 } catch (Throwable e) { | 106 } catch (Throwable e) { |
107 e.addSuppressed(new RuntimeException(String.format("Parsing of Node %s failed.", ElementUtils.getQualifiedName(rootType)), e)); | 107 RuntimeException e2 = new RuntimeException(String.format("Parsing of Node %s failed.", ElementUtils.getQualifiedName(rootType))); |
108 throw e; | 108 e2.addSuppressed(e); |
109 throw e2; | |
109 } | 110 } |
110 if (node == null && !enclosedNodes.isEmpty()) { | 111 if (node == null && !enclosedNodes.isEmpty()) { |
111 node = new NodeData(context, rootType); | 112 node = new NodeData(context, rootType); |
112 } | 113 } |
113 | 114 |
145 } | 146 } |
146 | 147 |
147 node.getFields().addAll(parseFields(lookupTypes, members)); | 148 node.getFields().addAll(parseFields(lookupTypes, members)); |
148 node.getChildren().addAll(parseChildren(lookupTypes, members)); | 149 node.getChildren().addAll(parseChildren(lookupTypes, members)); |
149 node.getChildExecutions().addAll(parseExecutions(node.getFields(), node.getChildren(), members)); | 150 node.getChildExecutions().addAll(parseExecutions(node.getFields(), node.getChildren(), members)); |
150 node.setExecutableTypes(groupExecutableTypes(parseExecutableTypeData(members, node.getChildExecutions().size(), context.getFrameTypes()))); | 151 node.getExecutableTypes().addAll(parseExecutableTypeData(members, node.getChildExecutions().size(), context.getFrameTypes(), false)); |
151 | 152 |
152 initializeExecutableTypes(node); | 153 initializeExecutableTypes(node); |
153 initializeImportGuards(node, lookupTypes, members); | 154 initializeImportGuards(node, lookupTypes, members); |
155 initializeChildren(node); | |
154 | 156 |
155 if (node.hasErrors()) { | 157 if (node.hasErrors()) { |
156 return node; // error sync point | 158 return node; // error sync point |
157 } | 159 } |
158 | |
159 initializeChildren(node); | |
160 | 160 |
161 if (node.hasErrors()) { | 161 if (node.hasErrors()) { |
162 return node; // error sync point | 162 return node; // error sync point |
163 } | 163 } |
164 | 164 |
168 node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(members)); | 168 node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(members)); |
169 | 169 |
170 if (node.hasErrors()) { | 170 if (node.hasErrors()) { |
171 return node; // error sync point | 171 return node; // error sync point |
172 } | 172 } |
173 initializeSpecializations(members, node); | |
174 initializeExecutableTypeHierarchy(node); | |
173 | 175 |
174 verifySpecializationSameLength(node); | 176 verifySpecializationSameLength(node); |
175 initializeSpecializations(members, node); | |
176 initializeShortCircuits(node); // requires specializations and polymorphic specializations | 177 initializeShortCircuits(node); // requires specializations and polymorphic specializations |
177 | 178 |
178 verifyVisibilities(node); | 179 verifyVisibilities(node); |
179 verifyMissingAbstractMethods(node, members); | 180 verifyMissingAbstractMethods(node, members); |
180 verifyConstructors(node); | 181 verifyConstructors(node); |
181 verifyNamingConvention(node.getShortCircuits(), "needs"); | 182 verifyNamingConvention(node.getShortCircuits(), "needs"); |
182 verifySpecializationThrows(node); | 183 verifySpecializationThrows(node); |
183 return node; | 184 return node; |
185 } | |
186 | |
187 private static void initializeExecutableTypeHierarchy(NodeData node) { | |
188 SpecializationData polymorphic = node.getPolymorphicSpecialization(); | |
189 if (polymorphic != null) { | |
190 boolean polymorphicSignatureFound = false; | |
191 TypeMirror frame = polymorphic.getFrame() != null ? polymorphic.getFrame().getType() : null; | |
192 ExecutableTypeData polymorphicType = new ExecutableTypeData(polymorphic.getReturnType().getType(), "execute", frame, TemplateMethod.getSignatureTypes(polymorphic)); | |
193 for (ExecutableTypeData type : node.getExecutableTypes()) { | |
194 if (polymorphicType.sameSignature(type)) { | |
195 polymorphicSignatureFound = true; | |
196 break; | |
197 } | |
198 } | |
199 | |
200 if (!polymorphicSignatureFound) { | |
201 node.getExecutableTypes().add(polymorphicType); | |
202 } | |
203 } | |
204 | |
205 List<ExecutableTypeData> rootTypes = buildExecutableHierarchy(node); | |
206 List<ExecutableTypeData> additionalAbstractRootTypes = new ArrayList<>(); | |
207 for (int i = 1; i < rootTypes.size(); i++) { | |
208 ExecutableTypeData rootType = rootTypes.get(i); | |
209 if (rootType.isAbstract()) { | |
210 // cannot implemement root | |
211 additionalAbstractRootTypes.add(rootType); | |
212 } else { | |
213 node.getExecutableTypes().remove(rootType); | |
214 } | |
215 } | |
216 if (!additionalAbstractRootTypes.isEmpty()) { | |
217 node.addError("Incompatible abstract execute methods found %s.", rootTypes); | |
218 } | |
219 | |
220 } | |
221 | |
222 private static List<ExecutableTypeData> buildExecutableHierarchy(NodeData node) { | |
223 List<ExecutableTypeData> executes = node.getExecutableTypes(); | |
224 if (executes.isEmpty()) { | |
225 return Collections.emptyList(); | |
226 } | |
227 List<ExecutableTypeData> hierarchyExecutes = new ArrayList<>(executes); | |
228 Collections.sort(hierarchyExecutes); | |
229 ExecutableTypeData parent = hierarchyExecutes.get(0); | |
230 ListIterator<ExecutableTypeData> executesIterator = hierarchyExecutes.listIterator(1); | |
231 buildExecutableHierarchy(node, parent, executesIterator); | |
232 return hierarchyExecutes; | |
233 } | |
234 | |
235 private static void buildExecutableHierarchy(NodeData node, ExecutableTypeData parent, ListIterator<ExecutableTypeData> executesIterator) { | |
236 while (executesIterator.hasNext()) { | |
237 ExecutableTypeData other = executesIterator.next(); | |
238 if (other.canDelegateTo(node, parent)) { | |
239 parent.addDelegatedFrom(other); | |
240 executesIterator.remove(); | |
241 } | |
242 } | |
243 for (int i = 1; i < parent.getDelegatedFrom().size(); i++) { | |
244 buildExecutableHierarchy(node, parent.getDelegatedFrom().get(i - 1), parent.getDelegatedFrom().listIterator(i)); | |
245 } | |
184 } | 246 } |
185 | 247 |
186 private List<Element> loadMembers(TypeElement templateType) { | 248 private List<Element> loadMembers(TypeElement templateType) { |
187 List<Element> members = new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType)); | 249 List<Element> members = new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType)); |
188 | 250 |
510 executions.add(new NodeExecutionData(child, i, varArgsIndex, shortCircuit)); | 572 executions.add(new NodeExecutionData(child, i, varArgsIndex, shortCircuit)); |
511 } | 573 } |
512 return executions; | 574 return executions; |
513 } | 575 } |
514 | 576 |
515 private List<ExecutableTypeData> parseExecutableTypeData(List<? extends Element> elements, int signatureSize, List<TypeMirror> frameTypes) { | 577 private List<ExecutableTypeData> parseExecutableTypeData(List<? extends Element> elements, int signatureSize, List<TypeMirror> frameTypes, boolean includeFinals) { |
516 List<ExecutableTypeData> typeData = new ArrayList<>(); | 578 List<ExecutableTypeData> typeData = new ArrayList<>(); |
517 for (ExecutableElement method : ElementFilter.methodsIn(elements)) { | 579 for (ExecutableElement method : ElementFilter.methodsIn(elements)) { |
518 Set<Modifier> modifiers = method.getModifiers(); | 580 Set<Modifier> modifiers = method.getModifiers(); |
519 if (modifiers.contains(Modifier.PRIVATE) || modifiers.contains(Modifier.STATIC)) { | 581 if (modifiers.contains(Modifier.PRIVATE) || modifiers.contains(Modifier.STATIC)) { |
520 continue; | 582 continue; |
521 } | 583 } |
584 if (!includeFinals && modifiers.contains(Modifier.FINAL)) { | |
585 continue; | |
586 } | |
587 | |
522 if (!method.getSimpleName().toString().startsWith("execute")) { | 588 if (!method.getSimpleName().toString().startsWith("execute")) { |
523 continue; | 589 continue; |
524 } | 590 } |
525 if (ElementUtils.findAnnotationMirror(context.getEnvironment(), method, Specialization.class) != null) { | 591 if (ElementUtils.findAnnotationMirror(context.getEnvironment(), method, Specialization.class) != null) { |
526 continue; | 592 continue; |
543 | 609 |
544 typeData.add(executableType); | 610 typeData.add(executableType); |
545 } | 611 } |
546 | 612 |
547 Collections.sort(typeData); | 613 Collections.sort(typeData); |
614 | |
615 List<String> names = new ArrayList<>(); | |
616 for (ExecutableTypeData type : typeData) { | |
617 names.add(type.getUniqueName()); | |
618 } | |
619 while (renameDuplicateIds(names)) { | |
620 // fix point | |
621 } | |
622 | |
623 for (int i = 0; i < typeData.size(); i++) { | |
624 typeData.get(i).setUniqueName(names.get(i)); | |
625 } | |
626 | |
548 return typeData; | 627 return typeData; |
549 } | 628 } |
550 | 629 |
551 private void initializeExecutableTypes(NodeData node) { | 630 private void initializeExecutableTypes(NodeData node) { |
552 List<ExecutableTypeData> allExecutes = node.getExecutableTypes(); | 631 List<ExecutableTypeData> allExecutes = node.getExecutableTypes(); |
580 frameType = context.getType(void.class); | 659 frameType = context.getType(void.class); |
581 } | 660 } |
582 | 661 |
583 node.setFrameType(frameType); | 662 node.setFrameType(frameType); |
584 | 663 |
585 int totalGenericCount = 0; | 664 boolean genericFound = false; |
586 int totalVoidCount = 0; | 665 for (ExecutableTypeData type : node.getExecutableTypes()) { |
587 for (Integer evaluatedCount : evaluatedCounts) { | 666 if (!type.hasUnexpectedValue(context)) { |
588 List<ExecutableTypeData> genericExecutes = node.findGenericExecutableTypes(context, evaluatedCount); | 667 genericFound = true; |
589 int genericCount = 0; | 668 break; |
590 int voidCount = 0; | 669 } |
591 for (ExecutableTypeData executableTypeData : genericExecutes) { | |
592 if (!executableTypeData.getMethod().getModifiers().contains(Modifier.FINAL)) { | |
593 if (ElementUtils.isVoid(executableTypeData.getReturnType())) { | |
594 voidCount++; | |
595 } else { | |
596 genericCount++; | |
597 } | |
598 } | |
599 } | |
600 // multiple generic execute | |
601 if (evaluatedCount == 0) { | |
602 if (voidCount > 1) { | |
603 List<String> methodSignatures = new ArrayList<>(); | |
604 for (ExecutableTypeData type : genericExecutes) { | |
605 if (context.isType(type.getReturnType(), void.class)) { | |
606 methodSignatures.add(ElementUtils.createReferenceName(type.getMethod())); | |
607 } | |
608 } | |
609 node.addWarning("Multiple accessible and overridable generic execute methods found %s. Remove all but one or mark all but one as final.", methodSignatures); | |
610 } else if (genericCount > 1) { | |
611 List<String> methodSignatures = new ArrayList<>(); | |
612 for (ExecutableTypeData type : genericExecutes) { | |
613 if (!context.isType(type.getReturnType(), void.class)) { | |
614 methodSignatures.add(ElementUtils.createReferenceName(type.getMethod())); | |
615 } | |
616 } | |
617 node.addWarning("Multiple accessible and overridable generic execute methods found %s. Remove all but one or mark all but one as final.", methodSignatures); | |
618 } | |
619 } | |
620 totalGenericCount += genericCount; | |
621 totalVoidCount += voidCount; | |
622 } | 670 } |
623 | 671 |
624 // no generic executes | 672 // no generic executes |
625 if (totalGenericCount + totalVoidCount == 0) { | 673 if (!genericFound) { |
626 node.addError("No accessible and overridable generic execute method found. Generic execute methods usually have the " | 674 node.addError("No accessible and overridable generic execute method found. Generic execute methods usually have the " |
627 + "signature 'public abstract {Type} execute(VirtualFrame)' and must not throw any checked exceptions."); | 675 + "signature 'public abstract {Type} execute(VirtualFrame)' and must not throw any checked exceptions."); |
628 } | 676 } |
629 | 677 |
630 int nodeChildDeclarations = 0; | 678 int nodeChildDeclarations = 0; |
654 for (NodeChildData child : node.getChildren()) { | 702 for (NodeChildData child : node.getChildren()) { |
655 child.addError("Unnecessary @NodeChild declaration. All evaluated child values are provided as parameters in execute methods."); | 703 child.addError("Unnecessary @NodeChild declaration. All evaluated child values are provided as parameters in execute methods."); |
656 } | 704 } |
657 } | 705 } |
658 | 706 |
659 } | |
660 | |
661 private static Map<Integer, List<ExecutableTypeData>> groupExecutableTypes(List<ExecutableTypeData> executableTypes) { | |
662 Map<Integer, List<ExecutableTypeData>> groupedTypes = new TreeMap<>(); | |
663 for (ExecutableTypeData type : executableTypes) { | |
664 int evaluatedCount = type.getEvaluatedCount(); | |
665 | |
666 List<ExecutableTypeData> types = groupedTypes.get(evaluatedCount); | |
667 if (types == null) { | |
668 types = new ArrayList<>(); | |
669 groupedTypes.put(evaluatedCount, types); | |
670 } | |
671 types.add(type); | |
672 } | |
673 | |
674 for (List<ExecutableTypeData> types : groupedTypes.values()) { | |
675 Collections.sort(types); | |
676 } | |
677 return groupedTypes; | |
678 } | 707 } |
679 | 708 |
680 private void initializeChildren(NodeData node) { | 709 private void initializeChildren(NodeData node) { |
681 initializeExecuteWith(node); | 710 initializeExecuteWith(node); |
682 | 711 |
757 } | 786 } |
758 List<TypeMirror> frameTypes = Collections.emptyList(); | 787 List<TypeMirror> frameTypes = Collections.emptyList(); |
759 if (parentNode.getFrameType() != null) { | 788 if (parentNode.getFrameType() != null) { |
760 frameTypes = Arrays.asList(parentNode.getFrameType()); | 789 frameTypes = Arrays.asList(parentNode.getFrameType()); |
761 } | 790 } |
762 node.setExecutableTypes(groupExecutableTypes(parseExecutableTypeData(members, child.getExecuteWith().size(), frameTypes))); | 791 node.getExecutableTypes().addAll(parseExecutableTypeData(members, child.getExecuteWith().size(), frameTypes, true)); |
763 node.setFrameType(parentNode.getFrameType()); | 792 node.setFrameType(parentNode.getFrameType()); |
764 return node; | 793 return node; |
765 } | 794 } |
766 | 795 |
767 private List<TypeMirror> createAllowedChildFrameTypes(NodeData parentNode) { | 796 private List<TypeMirror> createAllowedChildFrameTypes(NodeData parentNode) { |
1257 NodeExecutionData execution = spec.getExecution(); | 1286 NodeExecutionData execution = spec.getExecution(); |
1258 Collection<TypeMirror> allowedTypes; | 1287 Collection<TypeMirror> allowedTypes; |
1259 if (execution == null) { | 1288 if (execution == null) { |
1260 allowedTypes = spec.getAllowedTypes(); | 1289 allowedTypes = spec.getAllowedTypes(); |
1261 } else { | 1290 } else { |
1262 allowedTypes = node.getPossibleTypes(execution); | 1291 allowedTypes = node.getGenericTypes(execution); |
1263 } | 1292 } |
1264 if (allowedTypes.size() == 1) { | 1293 if (allowedTypes.size() == 1) { |
1265 return allowedTypes.iterator().next(); | 1294 return allowedTypes.iterator().next(); |
1266 } else { | 1295 } else { |
1267 return ElementUtils.getCommonSuperType(context, allowedTypes.toArray(new TypeMirror[allowedTypes.size()])); | 1296 return ElementUtils.getCommonSuperType(context, allowedTypes.toArray(new TypeMirror[allowedTypes.size()])); |
1299 return; | 1328 return; |
1300 } | 1329 } |
1301 | 1330 |
1302 SpecializationData generic = node.getGenericSpecialization(); | 1331 SpecializationData generic = node.getGenericSpecialization(); |
1303 | 1332 |
1304 List<TypeMirror> polymorphicSignature = new ArrayList<>(); | 1333 List<VariableElement> types = new ArrayList<>(); |
1305 List<Parameter> updatePolymorphic = Arrays.asList(); | 1334 |
1306 for (Parameter genericParameter : updatePolymorphic) { | 1335 Set<TypeMirror> frameTypes = new HashSet<>(); |
1336 for (SpecializationData specialization : node.getSpecializations()) { | |
1337 if (specialization.getFrame() != null) { | |
1338 frameTypes.add(specialization.getFrame().getType()); | |
1339 } | |
1340 } | |
1341 if (!frameTypes.isEmpty()) { | |
1342 TypeMirror frameType; | |
1343 if (frameTypes.size() == 1) { | |
1344 frameType = frameTypes.iterator().next(); | |
1345 } else { | |
1346 frameType = context.getType(Frame.class); | |
1347 } | |
1348 types.add(new CodeVariableElement(frameType, "frameValue")); | |
1349 } | |
1350 | |
1351 TypeMirror returnType = null; | |
1352 int index = 0; | |
1353 for (Parameter genericParameter : generic.getReturnTypeAndParameters()) { | |
1354 TypeMirror polymorphicType; | |
1307 if (!genericParameter.getSpecification().isSignature()) { | 1355 if (!genericParameter.getSpecification().isSignature()) { |
1308 continue; | 1356 polymorphicType = genericParameter.getType(); |
1309 } | |
1310 | |
1311 Set<TypeMirror> usedTypes = new HashSet<>(); | |
1312 for (SpecializationData specialization : node.getSpecializations()) { | |
1313 if (!specialization.isSpecialized()) { | |
1314 continue; | |
1315 } | |
1316 Parameter parameter = specialization.findParameter(genericParameter.getLocalName()); | |
1317 if (parameter == null) { | |
1318 throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName()); | |
1319 } | |
1320 usedTypes.add(parameter.getType()); | |
1321 } | |
1322 | |
1323 TypeMirror polymorphicType; | |
1324 if (usedTypes.size() == 1) { | |
1325 polymorphicType = usedTypes.iterator().next(); | |
1326 } else { | 1357 } else { |
1327 polymorphicType = context.getType(Object.class); | 1358 Set<TypeMirror> usedTypes = new HashSet<>(); |
1328 } | 1359 for (SpecializationData specialization : node.getSpecializations()) { |
1329 polymorphicSignature.add(polymorphicType); | 1360 if (specialization.isUninitialized()) { |
1330 } | 1361 continue; |
1331 | 1362 } |
1332 SpecializationData polymorphic = new SpecializationData(node, generic, SpecializationKind.POLYMORPHIC); | 1363 Parameter parameter = specialization.findParameter(genericParameter.getLocalName()); |
1333 polymorphic.updateSignature(new TypeSignature(polymorphicSignature)); | 1364 if (parameter == specialization.getReturnType() && specialization.isFallback() && specialization.getMethod() == null) { |
1365 continue; | |
1366 } | |
1367 if (parameter == null) { | |
1368 throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName()); | |
1369 } | |
1370 usedTypes.add(parameter.getType()); | |
1371 } | |
1372 | |
1373 if (usedTypes.size() == 1) { | |
1374 polymorphicType = usedTypes.iterator().next(); | |
1375 | |
1376 if (node.getTypeSystem().hasImplicitSourceTypes(polymorphicType)) { | |
1377 polymorphicType = context.getType(Object.class); | |
1378 } | |
1379 } else { | |
1380 polymorphicType = context.getType(Object.class); | |
1381 } | |
1382 } | |
1383 if (genericParameter == generic.getReturnType()) { | |
1384 returnType = polymorphicType; | |
1385 } else { | |
1386 types.add(new CodeVariableElement(polymorphicType, "param" + index)); | |
1387 } | |
1388 index++; | |
1389 } | |
1390 | |
1391 SpecializationMethodParser parser = new SpecializationMethodParser(context, node); | |
1392 | |
1393 SpecializationData polymorphic = parser.create("Polymorphic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, types); | |
1394 polymorphic.setKind(SpecializationKind.POLYMORPHIC); | |
1334 node.getSpecializations().add(polymorphic); | 1395 node.getSpecializations().add(polymorphic); |
1335 } | 1396 } |
1336 | 1397 |
1337 private void initializeShortCircuits(NodeData node) { | 1398 private void initializeShortCircuits(NodeData node) { |
1338 Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits()); | 1399 Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits()); |