Mercurial > hg > truffle
comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java @ 18775:a069a87b9a02
Truffle-DSL: Added tests and verification of overridable generic execute methods.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 05 Jan 2015 01:31:08 +0100 |
parents | 7382bbcac3a3 |
children | c0fb70634640 |
comparison
equal
deleted
inserted
replaced
18774:674c8a6d5e6c | 18775:a069a87b9a02 |
---|---|
146 | 146 |
147 if (node.hasErrors()) { | 147 if (node.hasErrors()) { |
148 return node; // error sync point | 148 return node; // error sync point |
149 } | 149 } |
150 | 150 |
151 node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node).parse(elements))); | 151 initializeExecutableTypes(elements, node); |
152 initializeChildren(node); | 152 initializeChildren(node); |
153 | 153 |
154 // ensure the processed element has at least one @Specialization annotation. | 154 // ensure the processed element has at least one @Specialization annotation. |
155 boolean foundSpecialization = false; | 155 boolean foundSpecialization = false; |
156 for (ExecutableElement method : ElementFilter.methodsIn(elements)) { | 156 for (ExecutableElement method : ElementFilter.methodsIn(elements)) { |
372 if (castNodeType != null) { | 372 if (castNodeType != null) { |
373 childType = castNodeType; | 373 childType = castNodeType; |
374 } | 374 } |
375 | 375 |
376 Element getter = findGetter(elements, name, childType); | 376 Element getter = findGetter(elements, name, childType); |
377 | |
378 NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality); | 377 NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality); |
379 | 378 |
380 parsedChildren.add(nodeChild); | 379 parsedChildren.add(nodeChild); |
381 | 380 |
382 if (nodeChild.getNodeType() == null) { | 381 if (nodeChild.getNodeType() == null) { |
525 executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit)); | 524 executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit)); |
526 } | 525 } |
527 return executions; | 526 return executions; |
528 } | 527 } |
529 | 528 |
529 private void initializeExecutableTypes(List<Element> elements, NodeData node) { | |
530 node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node).parse(elements))); | |
531 List<ExecutableTypeData> genericExecutes = node.getThisExecution().getChild().findGenericExecutableTypes(context); | |
532 | |
533 List<ExecutableTypeData> overridableGenericExecutes = new ArrayList<>(); | |
534 for (ExecutableTypeData executableTypeData : genericExecutes) { | |
535 if (!executableTypeData.getMethod().getModifiers().contains(Modifier.FINAL)) { | |
536 overridableGenericExecutes.add(executableTypeData); | |
537 } | |
538 } | |
539 | |
540 if (overridableGenericExecutes.isEmpty()) { | |
541 node.addError("No accessible and overridable generic execute method found. Generic execute methods usually have the " | |
542 + "signature 'public abstract {Type} executeGeneric(VirtualFrame)' and must not throw any checked exceptions."); | |
543 } | |
544 | |
545 if (overridableGenericExecutes.size() > 1) { | |
546 List<String> methodSignatures = new ArrayList<>(); | |
547 for (ExecutableTypeData type : overridableGenericExecutes) { | |
548 methodSignatures.add(type.createReferenceName()); | |
549 } | |
550 node.addWarning("Multiple accessible and overridable generic execute methods found %s. Remove all but one or mark all but one as final.", methodSignatures); | |
551 } | |
552 } | |
553 | |
530 private static Map<Integer, List<ExecutableTypeData>> groupExecutableTypes(List<ExecutableTypeData> executableTypes) { | 554 private static Map<Integer, List<ExecutableTypeData>> groupExecutableTypes(List<ExecutableTypeData> executableTypes) { |
531 Map<Integer, List<ExecutableTypeData>> groupedTypes = new TreeMap<>(); | 555 Map<Integer, List<ExecutableTypeData>> groupedTypes = new TreeMap<>(); |
532 for (ExecutableTypeData type : executableTypes) { | 556 for (ExecutableTypeData type : executableTypes) { |
533 int evaluatedCount = type.getEvaluatedCount(); | 557 int evaluatedCount = type.getEvaluatedCount(); |
534 | 558 |
554 nodeChild.addError("Node type '%s' is invalid or not a valid Node.", ElementUtils.getQualifiedName(nodeChild.getNodeType())); | 578 nodeChild.addError("Node type '%s' is invalid or not a valid Node.", ElementUtils.getQualifiedName(nodeChild.getNodeType())); |
555 } else if (!ElementUtils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) { | 579 } else if (!ElementUtils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) { |
556 nodeChild.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(), | 580 nodeChild.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(), |
557 NodeChild.class.getSimpleName(), ElementUtils.getSimpleName(node.getTypeSystem().getTemplateType()), | 581 NodeChild.class.getSimpleName(), ElementUtils.getSimpleName(node.getTypeSystem().getTemplateType()), |
558 ElementUtils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType())); | 582 ElementUtils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType())); |
583 } else if (nodeChild.findAnyGenericExecutableType(context) == null) { | |
584 nodeChild.addError("No generic execute method found for child type %s. Generic execute methods usually have the signature 'Object executeGeneric(VirtualFrame)'.", | |
585 ElementUtils.getQualifiedName(nodeChild.getNodeType())); | |
559 } | 586 } |
560 if (fieldNodeData != null) { | 587 if (fieldNodeData != null) { |
561 List<ExecutableTypeData> types = nodeChild.findGenericExecutableTypes(context); | 588 List<ExecutableTypeData> types = nodeChild.findGenericExecutableTypes(context); |
562 if (types.isEmpty()) { | 589 if (types.isEmpty()) { |
563 AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(nodeChild.getMessageAnnotation(), "executeWith"); | 590 AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(nodeChild.getMessageAnnotation(), "executeWith"); |
981 } | 1008 } |
982 | 1009 |
983 NodeChildData child = execution.getChild(); | 1010 NodeChildData child = execution.getChild(); |
984 TypeData genericType = null; | 1011 TypeData genericType = null; |
985 if (types.size() == 1) { | 1012 if (types.size() == 1) { |
986 ExecutableTypeData executable = child.findExecutableType(context, types.iterator().next()); | 1013 TypeData singleType = types.iterator().next(); |
1014 ExecutableTypeData executable = child.findExecutableType(singleType); | |
987 if (executable != null && (signatureIndex == 0 || !executable.hasUnexpectedValue(context))) { | 1015 if (executable != null && (signatureIndex == 0 || !executable.hasUnexpectedValue(context))) { |
988 genericType = types.iterator().next(); | 1016 genericType = singleType; |
989 } | 1017 } |
990 } | 1018 } |
991 if (genericType == null) { | 1019 if (genericType == null) { |
992 genericType = child.findAnyGenericExecutableType(context).getType(); | 1020 ExecutableTypeData type = child.findAnyGenericExecutableType(context); |
1021 if (type == null) { | |
1022 throw new AssertionError("No generic type not yet catched by parser."); | |
1023 } | |
1024 genericType = type.getType(); | |
993 } | 1025 } |
994 return genericType.getPrimitiveType(); | 1026 return genericType.getPrimitiveType(); |
995 } | 1027 } |
996 } | 1028 } |
997 | 1029 |