Mercurial > hg > graal-jvmci-8
diff graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java @ 8252:0905d796944a
Refactored codegen error model to make error redirection a lot easier.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Wed, 13 Mar 2013 19:58:28 +0100 |
parents | cb70ed101b5f |
children | 4dc7034317ec |
line wrap: on
line diff
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Wed Mar 13 19:58:28 2013 +0100 @@ -28,6 +28,7 @@ import javax.lang.model.element.*; import javax.lang.model.type.*; import javax.lang.model.util.*; +import javax.tools.Diagnostic.*; import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.api.nodes.Node.Child; @@ -56,13 +57,36 @@ try { parsedNodes = new HashMap<>(); node = resolveNode((TypeElement) element); + if (Log.DEBUG) { + NodeData parsed = parsedNodes.get(Utils.getQualifiedName((TypeElement) element)); + if (node != null) { + String dump = parsed.dump(); + log.message(Kind.ERROR, null, null, null, dump); + System.out.println(dump); + } + } } finally { parsedNodes = null; } + return node; } @Override + protected NodeData filterErrorElements(NodeData model) { + for (Iterator<NodeData> iterator = model.getDeclaredChildren().iterator(); iterator.hasNext();) { + NodeData node = filterErrorElements(iterator.next()); + if (node == null) { + iterator.remove(); + } + } + if (model.hasErrors()) { + return null; + } + return model; + } + + @Override public boolean isDelegateToRootDeclaredType() { return true; } @@ -82,9 +106,11 @@ children.add(childNode); } } + NodeData rootNode = parseNode(rootType); - if (rootNode == null && children.size() > 0) { - rootNode = new NodeData(rootType, null, rootType.getSimpleName().toString()); + boolean hasErrors = rootNode != null ? rootNode.hasErrors() : false; + if ((rootNode == null || hasErrors) && children.size() > 0) { + rootNode = new NodeData(rootType, rootType.getSimpleName().toString()); } parsedNodes.put(typeName, rootNode); @@ -94,17 +120,6 @@ rootNode.setDeclaredChildren(children); } - if (Log.DEBUG) { - NodeData parsed = parsedNodes.get(typeName); - if (parsed != null) { - String dump = parsed.dump(); - String valid = rootNode != null ? "" : " failed"; - String msg = String.format("Node parsing %s : %s", valid, dump); - log.error(msg); - System.out.println(msg); - } - } - return rootNode; } @@ -121,7 +136,8 @@ } if (type.getModifiers().contains(Modifier.PRIVATE)) { - return null; // not visible + // TODO error message here!? + return null; // not visible, not a node } TypeElement nodeType; @@ -135,43 +151,32 @@ } NodeData nodeData = parseNodeData(type, nodeType); - if (nodeData == null) { - return null; + if (nodeData.hasErrors()) { + return nodeData; // error sync point } List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(type)); - nodeData.setExtensionElements(getExtensionParser().parseAll(type, elements)); + nodeData.setExtensionElements(getExtensionParser().parseAll(nodeData, elements)); if (nodeData.getExtensionElements() != null) { elements.addAll(nodeData.getExtensionElements()); } + parseMethods(nodeData, elements); - if (!parseMethods(nodeData, elements)) { - return null; + if (nodeData.hasErrors()) { + return nodeData; } List<NodeData> nodes; if (needsSplit) { nodes = splitNodeData(nodeData); - if (nodes == null) { - return null; - } } else { nodes = new ArrayList<>(); nodes.add(nodeData); } - boolean valid = true; for (NodeData splittedNode : nodes) { - if (!finalizeSpecializations(splittedNode)) { - valid = false; - } - if (!verifyNode(splittedNode)) { - valid = false; - } - } - - if (!valid) { - return null; + finalizeSpecializations(splittedNode); + verifyNode(splittedNode); } if (needsSplit) { @@ -237,31 +242,25 @@ return grouped; } - private boolean parseMethods(final NodeData node, List<Element> elements) { + private void parseMethods(final NodeData node, List<Element> elements) { node.setGuards(new GuardParser(context, node, node.getTypeSystem()).parse(elements)); node.setShortCircuits(new ShortCircuitParser(context, node).parse(elements)); node.setSpecializationListeners(new SpecializationListenerParser(context, node).parse(elements)); List<SpecializationData> generics = new GenericParser(context, node).parse(elements); List<SpecializationData> specializations = new SpecializationMethodParser(context, node).parse(elements); - if (generics == null || specializations == null || node.getGuards() == null || node.getShortCircuits() == null || node.getSpecializationListeners() == null) { - return false; - } - List<SpecializationData> allSpecializations = new ArrayList<>(); allSpecializations.addAll(generics); allSpecializations.addAll(specializations); node.setSpecializations(allSpecializations); - - return true; } - private boolean finalizeSpecializations(final NodeData node) { + private void finalizeSpecializations(final NodeData node) { List<SpecializationData> specializations = new ArrayList<>(node.getSpecializations()); if (specializations.isEmpty()) { - return true; + return; } List<SpecializationData> generics = new ArrayList<>(); @@ -273,22 +272,18 @@ if (generics.size() == 1 && specializations.size() == 1) { for (SpecializationData generic : generics) { - log.error(generic.getMethod(), "@%s defined but no @%s.", Generic.class.getSimpleName(), Specialization.class.getSimpleName()); + generic.addError("@%s defined but no @%s.", Generic.class.getSimpleName(), Specialization.class.getSimpleName()); } } SpecializationData genericSpecialization = null; if (generics.size() > 1) { for (SpecializationData generic : generics) { - log.error(generic.getMethod(), "Only @%s is allowed per operation.", Generic.class.getSimpleName()); + generic.addError("Only @%s is allowed per operation.", Generic.class.getSimpleName()); } - return false; + return; } else if (generics.size() == 1) { genericSpecialization = generics.get(0); - if (!node.needsRewrites(context)) { - log.error(genericSpecialization.getMethod(), "Generic specialization is not reachable.", Generic.class.getSimpleName()); - return false; - } } else if (node.needsRewrites(context)) { SpecializationData specialization = specializations.get(0); GenericParser parser = new GenericParser(context, node); @@ -343,8 +338,6 @@ for (SpecializationData specialization : specializations) { specialization.setId(findUniqueSpecializationId(specialization)); } - - return true; } private static String findUniqueSpecializationId(SpecializationData specialization) { @@ -435,28 +428,18 @@ } } - private boolean verifyNode(NodeData nodeData) { + private void verifyNode(NodeData nodeData) { // verify specialization parameter length - if (!verifySpecializationParameters(nodeData)) { - return false; - } + verifySpecializationParameters(nodeData); // verify order is not ambiguous - if (!verifySpecializationOrder(nodeData)) { - return false; - } + verifySpecializationOrder(nodeData); - if (!verifyMissingAbstractMethods(nodeData)) { - return false; - } + verifyMissingAbstractMethods(nodeData); - if (!assignShortCircuitsToSpecializations(nodeData)) { - return false; - } + assignShortCircuitsToSpecializations(nodeData); - if (!verifyConstructors(nodeData)) { - return false; - } + verifyConstructors(nodeData); // if (!verifyNamingConvention(specializations, "do")) { // return null; @@ -466,54 +449,42 @@ // return null; // } - if (!verifyNamingConvention(nodeData.getShortCircuits(), "needs")) { - return false; - } + verifyNamingConvention(nodeData.getShortCircuits(), "needs"); - if (!verifySpecializationThrows(nodeData)) { - return false; - } - - return true; + verifySpecializationThrows(nodeData); } private NodeData parseNodeData(TypeElement templateType, TypeElement nodeType) { List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(nodeType)); List<TypeElement> typeHierarchy = findSuperClasses(new ArrayList<TypeElement>(), nodeType); Collections.reverse(typeHierarchy); + NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString()); AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); if (typeSystemMirror == null) { - log.error(templateType, "No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), nodeType.getQualifiedName().toString()); - return null; + nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), nodeType.getQualifiedName().toString()); + return nodeData; } TypeMirror typeSytemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value"); final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true); if (typeSystem == null) { - log.error(templateType, "The used type system '%s' is invalid.", Utils.getQualifiedName(typeSytemType)); - return null; + nodeData.addError("The used type system '%s' is invalid.", Utils.getQualifiedName(typeSytemType)); + return nodeData; } - NodeData nodeData = new NodeData(templateType, typeSystem, templateType.getSimpleName().toString()); nodeData.setNodeType(nodeType.asType()); + nodeData.setTypeSystem(typeSystem); List<ExecutableTypeData> executableTypes = filterExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)); - nodeData.setExecutableTypes(executableTypes); - parsedNodes.put(Utils.getQualifiedName(templateType), nodeData); - - List<NodeFieldData> fields = parseFields(nodeData, elements, typeHierarchy); - if (fields == null) { - return null; - } - nodeData.setFields(fields); + nodeData.setFields(parseFields(nodeData, elements, typeHierarchy)); return nodeData; } - private boolean verifySpecializationParameters(NodeData nodeData) { + private static void verifySpecializationParameters(NodeData nodeData) { boolean valid = true; int args = -1; for (SpecializationData specializationData : nodeData.getSpecializations()) { @@ -531,17 +502,16 @@ } if (!valid) { for (SpecializationData specialization : nodeData.getSpecializations()) { - context.getLog().error(specialization.getMethod(), specialization.getMarkerAnnotation(), "All specializations must have the same number of arguments."); + specialization.addError("All specializations must have the same number of arguments."); } } - return valid; } - private boolean verifyMissingAbstractMethods(NodeData nodeData) { - if (nodeData.needsFactory()) { + private void verifyMissingAbstractMethods(NodeData nodeData) { + if (!nodeData.needsFactory()) { // missing abstract methods only needs to be implemented // if we need go generate factory for it. - return true; + return; } List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(nodeData.getTemplateType())); @@ -554,24 +524,20 @@ unusedElements.removeAll(nodeData.getExtensionElements()); } - boolean valid = true; for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) { if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) { - context.getLog().error(nodeData.getTemplateType(), "The type %s must implement the inherited abstract method %s.", Utils.getSimpleName(nodeData.getTemplateType()), - Utils.getReadableSignature(unusedMethod)); - valid = false; + nodeData.addError("The type %s must implement the inherited abstract method %s.", Utils.getSimpleName(nodeData.getTemplateType()), Utils.getReadableSignature(unusedMethod)); } } + } + + private void verifyConstructors(NodeData nodeData) { + if (!nodeData.needsRewrites(context)) { + // no specialization constructor is needed if the node never rewrites. + return; + } - return valid; - } - - private boolean verifyConstructors(NodeData nodeData) { TypeElement type = Utils.fromTypeMirror(nodeData.getNodeType()); - if (!nodeData.needsRewrites(context)) { - // no specialization constructor is needed if the node never rewrites. - return true; - } List<ExecutableElement> constructors = ElementFilter.constructorsIn(type.getEnclosedElements()); for (ExecutableElement e : constructors) { @@ -579,20 +545,17 @@ TypeMirror firstArg = e.getParameters().get(0).asType(); if (Utils.typeEquals(firstArg, nodeData.getNodeType())) { if (e.getModifiers().contains(Modifier.PRIVATE)) { - context.getLog().error(e, "The specialization constructor must not be private."); - return false; + nodeData.addError("The specialization constructor must not be private."); } else if (constructors.size() <= 1) { - context.getLog().error(e, "The specialization constructor must not be the only constructor. The definition of an alternative constructor is required."); - return false; + nodeData.addError("The specialization constructor must not be the only constructor. The definition of an alternative constructor is required."); } - return true; + return; } } } // not found - context.getLog().error(type, "Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type)); - return false; + nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type)); } private static List<ExecutableTypeData> filterExecutableTypes(List<ExecutableTypeData> executableTypes) { @@ -657,8 +620,6 @@ } } - boolean valid = true; - List<NodeFieldData> fields = new ArrayList<>(); for (VariableElement var : ElementFilter.fieldsIn(elements)) { if (var.getModifiers().contains(Modifier.STATIC)) { @@ -672,20 +633,10 @@ } NodeFieldData field = parseField(nodeData, var, shortCircuits); - if (field != null) { - if (field.getExecutionKind() != ExecutionKind.IGNORE) { - fields.add(field); - } - } else { - valid = false; + if (field.getExecutionKind() != ExecutionKind.IGNORE) { + fields.add(field); } } - - // TODO parse getters - if (!valid) { - return null; - } - sortByExecutionOrder(fields, executionDefinition == null ? Collections.<String> emptyList() : executionDefinition, typeHierarchy); return fields; } @@ -721,19 +672,15 @@ kind = null; } - NodeData fieldNodeData = null; + NodeFieldData fieldData = new NodeFieldData(var, findAccessElement(var), mirror, kind, execution); if (nodeType != null) { - fieldNodeData = resolveNode(Utils.fromTypeMirror(nodeType)); - Element errorElement = Utils.typeEquals(parentNodeData.getTemplateType().asType(), var.getEnclosingElement().asType()) ? var : parentNodeData.getTemplateType(); + NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(nodeType)); + fieldData.setNode(fieldNodeData); if (fieldNodeData == null) { - // TODO redirect errors from resolve. - context.getLog().error(errorElement, "Node type '%s' is invalid.", Utils.getQualifiedName(nodeType)); - return null; + fieldData.addError("Node type '%s' is invalid.", Utils.getQualifiedName(nodeType)); } else if (fieldNodeData.findGenericExecutableTypes(context).isEmpty()) { - // TODO better error handling for (no or multiple?) - context.getLog().error(errorElement, "No executable generic types found for node '%s'.", Utils.getQualifiedName(nodeType)); - return null; + fieldData.addError("No executable generic types found for node '%s'.", Utils.getQualifiedName(nodeType)); } // TODO correct handling of access elements @@ -741,7 +688,7 @@ execution = ExecutionKind.IGNORE; } } - return new NodeFieldData(fieldNodeData, var, findAccessElement(var), mirror, kind, execution); + return fieldData; } private Element findAccessElement(VariableElement variableElement) { @@ -795,17 +742,16 @@ }); } - private boolean assignShortCircuitsToSpecializations(NodeData node) { + private void assignShortCircuitsToSpecializations(NodeData node) { Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits()); boolean valid = true; - for (NodeFieldData field : node.filterFields(null, ExecutionKind.SHORT_CIRCUIT)) { String valueName = field.getName(); List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName); if (availableCircuits == null || availableCircuits.isEmpty()) { - log.error(node.getTemplateType(), "@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName); + node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName); valid = false; continue; } @@ -820,7 +766,7 @@ if (!sameMethodName) { for (ShortCircuitData circuit : availableCircuits) { - log.error(circuit.getMethod(), circuit.getMarkerAnnotation(), "All short circuits for short cut value '%s' must have the same method name.", valueName); + circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName); } valid = false; continue; @@ -835,7 +781,7 @@ } if (genericCircuit == null) { - log.error(node.getTemplateType(), "No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName); + node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName); valid = false; continue; } @@ -848,62 +794,42 @@ } if (!valid) { - return valid; + return; } NodeFieldData[] fields = node.filterFields(null, ExecutionKind.SHORT_CIRCUIT); for (SpecializationData specialization : node.getSpecializations()) { - ShortCircuitData[] assignedShortCuts = new ShortCircuitData[fields.length]; + List<ShortCircuitData> assignedShortCuts = new ArrayList<>(fields.length); for (int i = 0; i < fields.length; i++) { List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(fields[i].getName()); ShortCircuitData genericShortCircuit = null; + ShortCircuitData compatibleShortCircuit = null; for (ShortCircuitData circuit : availableShortCuts) { if (circuit.isGeneric()) { genericShortCircuit = circuit; } else if (circuit.isCompatibleTo(specialization)) { - assignedShortCuts[i] = circuit; + compatibleShortCircuit = circuit; } } - if (assignedShortCuts[i] == null) { - assignedShortCuts[i] = genericShortCircuit; + if (compatibleShortCircuit == null) { + compatibleShortCircuit = genericShortCircuit; } + assignedShortCuts.add(compatibleShortCircuit); } specialization.setShortCircuits(assignedShortCuts); } - return true; } - private boolean verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) { - boolean valid = true; + private static void verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) { for (int i = 0; i < methods.size(); i++) { TemplateMethod m1 = methods.get(i); if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) { - log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Naming convention: method name must start with '%s'.", prefix); - valid = false; + m1.addError("Naming convention: method name must start with '%s'.", prefix); } } - return valid; - } - - @SuppressWarnings("unused") - private boolean verifyNamesUnique(List<? extends TemplateMethod> methods) { - boolean valid = true; - for (int i = 0; i < methods.size(); i++) { - TemplateMethod m1 = methods.get(i); - for (int j = i + 1; j < methods.size(); j++) { - TemplateMethod m2 = methods.get(j); - - if (m1.getMethodName().equalsIgnoreCase(m2.getMethodName())) { - log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Method name '%s' used multiple times", m1.getMethodName()); - log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Method name '%s' used multiple times", m1.getMethodName()); - return false; - } - } - } - return valid; } private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) { @@ -958,7 +884,7 @@ return collection; } - private boolean verifySpecializationOrder(NodeData node) { + private static void verifySpecializationOrder(NodeData node) { TypeSystemData typeSystem = node.getTypeSystem(); List<SpecializationData> specializations = node.getSpecializations(); @@ -971,44 +897,39 @@ if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) { int specOrder = m1.getOrder() - m2.getOrder(); if (specOrder == 0) { - log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Order value %d used multiple times", m1.getOrder()); - log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Order value %d used multiple times", m1.getOrder()); - return false; + m1.addError("Order value %d used multiple times", m1.getOrder()); + m2.addError("Order value %d used multiple times", m1.getOrder()); + return; } else if ((specOrder < 0 && inferredOrder > 0) || (specOrder > 0 && inferredOrder < 0)) { - log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); - log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); - return false; + m1.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); + m2.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); + return; } } else if (inferredOrder == 0) { SpecializationData m = (m1.getOrder() == Specialization.DEFAULT_ORDER ? m1 : m2); - log.error(m.getMethod(), m.getMarkerAnnotation(), "Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this."); - return false; + m.addError("Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this."); + return; } } } - return true; } - private boolean verifySpecializationThrows(NodeData node) { + private static void verifySpecializationThrows(NodeData node) { Map<String, SpecializationData> specializationMap = new HashMap<>(); for (SpecializationData spec : node.getSpecializations()) { specializationMap.put(spec.getMethodName(), spec); } - boolean valid = true; for (SpecializationData sourceSpecialization : node.getSpecializations()) { if (sourceSpecialization.getExceptions() != null) { for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) { for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) { if (otherThrowsData != throwsData && Utils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) { - AnnotationValue javaClassValue = Utils.getAnnotationValue(throwsData.getAnnotationMirror(), "rewriteOn"); - log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), javaClassValue, "Duplicate exception type."); - valid = false; + throwsData.addError("Duplicate exception type."); } } } } } - return valid; } private static int compareSpecialization(TypeSystemData typeSystem, SpecializationData m1, SpecializationData m2) {