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