# HG changeset patch # User Christian Humer # Date 1363201108 -3600 # Node ID 0905d796944ac4240264505b0c8c9f708afa5198 # Parent cb70ed101b5f419e73f30f2fe3d60572fb73b651 Refactored codegen error model to make error redirection a lot easier. diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java Wed Mar 13 19:58:28 2013 +0100 @@ -58,12 +58,22 @@ if (!context.getTruffleTypes().verify(context, element, mirror)) { return null; } - return parse(element, mirror); + M model = parse(element, mirror); + if (model == null) { + return null; + } + + model.emitMessages((TypeElement) element, log); + return filterErrorElements(model); } finally { this.roundEnv = null; } } + protected M filterErrorElements(M model) { + return model.hasErrors() ? null : model; + } + protected abstract M parse(Element element, AnnotationMirror mirror); public abstract Class getAnnotationType(); diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java Wed Mar 13 19:58:28 2013 +0100 @@ -41,30 +41,6 @@ this.processingEnv = env; } - public void warning(Element element, String format, Object... args) { - message(Kind.WARNING, element, null, null, format, args); - } - - public void warning(Element element, AnnotationMirror mirror, String format, Object... args) { - message(Kind.WARNING, element, mirror, null, format, args); - } - - public void error(Element element, String format, Object... args) { - message(Kind.ERROR, element, null, null, format, args); - } - - public void error(String format, Object... args) { - message(Kind.ERROR, null, null, null, format, args); - } - - public void error(Element element, AnnotationMirror mirror, String format, Object... args) { - message(Kind.ERROR, element, mirror, null, format, args); - } - - public void error(Element element, AnnotationMirror mirror, AnnotationValue value, String format, Object... args) { - message(Kind.ERROR, element, mirror, value, format, args); - } - public void message(Kind kind, Element element, AnnotationMirror mirror, AnnotationValue value, String format, Object... args) { AnnotationMirror usedMirror = mirror; Element usedElement = element; diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java Wed Mar 13 19:58:28 2013 +0100 @@ -28,6 +28,7 @@ import javax.annotation.processing.*; import javax.lang.model.*; import javax.lang.model.element.*; +import javax.tools.Diagnostic.*; import com.oracle.truffle.codegen.processor.ProcessorContext.ProcessCallback; import com.oracle.truffle.codegen.processor.node.*; @@ -95,7 +96,7 @@ private static void handleThrowable(AnnotationProcessor generator, Throwable t, Element e) { String message = "Uncaught error in " + generator.getClass().getSimpleName() + " while processing " + e; - generator.getContext().getLog().error(e, message + ": " + Utils.printException(t)); + generator.getContext().getLog().message(Kind.ERROR, e, null, null, message + ": " + Utils.printException(t)); } @SuppressWarnings("unchecked") diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java Wed Mar 13 19:58:28 2013 +0100 @@ -26,6 +26,7 @@ import javax.lang.model.element.*; import javax.lang.model.type.*; +import javax.tools.Diagnostic.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.intrinsics.*; @@ -66,7 +67,7 @@ } for (String error : errors) { - context.getLog().error(element, mirror, error); + context.getLog().message(Kind.ERROR, element, mirror, null, error); } return false; diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java Wed Mar 13 19:58:28 2013 +0100 @@ -31,6 +31,7 @@ import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.api.*; import com.oracle.truffle.codegen.processor.api.element.*; +import com.oracle.truffle.codegen.processor.template.*; public class ExtensionParser { @@ -45,25 +46,25 @@ this.extensionContext = new ExtensionContextImpl(context.getEnvironment(), null, factory); } - public List parseAll(TypeElement typeElement, List elements) { + public List parseAll(Template template, List elements) { List generatedMethods = new ArrayList<>(); - parseElement(generatedMethods, typeElement); + parseElement(template, generatedMethods, template.getTemplateType()); List methods = ElementFilter.methodsIn(elements); for (ExecutableElement method : methods) { for (VariableElement var : method.getParameters()) { - parseElement(generatedMethods, var); + parseElement(template, generatedMethods, var); } - parseElement(generatedMethods, method); + parseElement(template, generatedMethods, method); } return generatedMethods; } - private void parseElement(List elements, Element element) { + private void parseElement(Template template, List elements, Element element) { List mirrors = element.getAnnotationMirrors(); for (AnnotationMirror mirror : mirrors) { - ExtensionProcessor processor = findProcessor(element, mirror); + ExtensionProcessor processor = findProcessor(template, mirror); if (processor != null) { try { factory.generatorAnnotationMirror = mirror; @@ -71,7 +72,7 @@ processor.process(extensionContext, mirror, element); elements.addAll(extensionContext.returnElements()); } catch (Throwable e) { - context.getLog().error(element, mirror, "Processor for '%s' failed with exception: \n\n%s.", Utils.getQualifiedName(mirror.getAnnotationType()), Utils.printException(e)); + template.addError("Processor for '%s' failed with exception: \n\n%s.", Utils.getQualifiedName(mirror.getAnnotationType()), Utils.printException(e)); } finally { factory.generatorAnnotationMirror = null; factory.generatorElement = null; @@ -80,7 +81,7 @@ } } - private ExtensionProcessor findProcessor(Element element, AnnotationMirror mirror) { + private ExtensionProcessor findProcessor(Template template, AnnotationMirror mirror) { String processorName = Utils.getQualifiedName(mirror.getAnnotationType()); ExtensionProcessor processor = null; if (extensions.containsKey(processorName)) { @@ -93,19 +94,19 @@ try { processorClass = Class.forName(className); } catch (ClassNotFoundException e) { - context.getLog().error(element, mirror, "Could not find processor class '%s' configured in '@%s'.", className, processorName); + template.addError("Could not find processor class '%s' configured in '@%s'.", className, processorName); return null; } try { processor = (ExtensionProcessor) processorClass.newInstance(); } catch (InstantiationException e) { - context.getLog().error(element, mirror, "Could not instantiate processor class '%s' configured in '@%s'.", className, processorName); + template.addError("Could not instantiate processor class '%s' configured in '@%s'.", className, processorName); return null; } catch (IllegalAccessException e) { - context.getLog().error(element, mirror, "Could not access processor class '%s' configured in '@%s'.", className, processorName); + template.addError("Could not access processor class '%s' configured in '@%s'.", className, processorName); return null; } catch (ClassCastException e) { - context.getLog().error(element, mirror, "Processor class '%s' configured in '@%s' does not implement '%s'.", className, processorName, ExtensionProcessor.class.getName()); + template.addError("Processor class '%s' configured in '@%s' does not implement '%s'.", className, processorName, ExtensionProcessor.class.getName()); return null; } } diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java Wed Mar 13 19:58:28 2013 +0100 @@ -44,10 +44,10 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { List types = new ArrayList<>(); - types.addAll(Arrays.asList(getNode().getTypeSystem().getPrimitiveTypeMirrors())); + types.addAll(getNode().getTypeSystem().getPrimitiveTypeMirrors()); types.add(getContext().getType(void.class)); - ParameterSpec returnTypeSpec = new ParameterSpec("executedValue", types.toArray(new TypeMirror[types.size()]), false, Cardinality.ONE); + ParameterSpec returnTypeSpec = new ParameterSpec("executedValue", types, false, Cardinality.ONE); List parameters = new ArrayList<>(); parameters.add(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), true)); diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java Wed Mar 13 19:58:28 2013 +0100 @@ -51,8 +51,7 @@ for (ExecutableTypeData type : execTypes) { types.add(type.getType().getPrimitiveType()); } - TypeMirror[] array = types.toArray(new TypeMirror[types.size()]); - return new ParameterSpec(valueName, array, false, Cardinality.ONE); + return new ParameterSpec(valueName, types, false, Cardinality.ONE); } @Override diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Wed Mar 13 19:58:28 2013 +0100 @@ -182,13 +182,17 @@ body.startCall(method.getSimpleName().toString()); } - private static String generatedGenericMethodName(SpecializationData specialization) { + private String generatedGenericMethodName(SpecializationData specialization) { final String prefix = "generic"; if (specialization == null) { return prefix; } + if (!specialization.getNode().getGenericSpecialization().isUseSpecializationsForGeneric() || !specialization.getNode().needsRewrites(context)) { + return prefix; + } + SpecializationData prev = null; for (SpecializationData current : specialization.getNode().getSpecializations()) { if (specialization == current) { @@ -250,26 +254,25 @@ } if (implicitGuards == null && explicitGuards == null && conditionPrefix != null && !conditionPrefix.isEmpty()) { - builder.startIf().string(conditionPrefix).end().startBlock(); + builder.startIf(); + builder.string(conditionPrefix); + builder.end().startBlock(); ifCount++; } builder.tree(guardedStatements); builder.end(ifCount); - if (ifCount > 0 && elseStatements != null) { - builder.startElseBlock(); + if (elseStatements != null && ifCount > 0) { builder.tree(elseStatements); - builder.end(); } - return builder.getRoot(); } private CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean onSpecialization) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; - if (guardedSpecialization.getGuards().length > 0) { + if (guardedSpecialization.getGuards().size() > 0) { // Explicitly specified guards for (SpecializationGuardData guard : guardedSpecialization.getGuards()) { if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) { @@ -514,9 +517,11 @@ clazz.add(createCreateSpecializedMethod(node, createVisibility)); } - if (node.needsRewrites(getContext())) { + if (node.needsRewrites(context)) { clazz.add(createSpecializeMethod(node)); + } + if (node.getGenericSpecialization() != null) { List genericMethods = createGeneratedGenericMethod(node); for (CodeExecutableElement method : genericMethods) { clazz.add(method); @@ -600,7 +605,7 @@ classType = types.getDeclaredType(Utils.fromTypeMirror(classType), wildcardNodeType); TypeMirror returnType = types.getDeclaredType(listType, classType); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getChildrenSignature"); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getExecutionSignature"); CodeTreeBuilder builder = method.createBuilder(); List signatureTypes = new ArrayList<>(); @@ -934,7 +939,7 @@ private List createGeneratedGenericMethod(NodeData node) { TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getActualType(); - if (node.getGenericSpecialization().isUseSpecializationsForGeneric()) { + if (node.getGenericSpecialization().isUseSpecializationsForGeneric() && node.needsRewrites(context)) { List methods = new ArrayList<>(); List specializations = node.getSpecializations(); @@ -974,18 +979,20 @@ CodeTree invokeMethod = invokeMethodBuilder.getRoot(); if (next != null) { - invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, false, invokeMethod, null); + CodeTreeBuilder nextBuilder = builder.create(); + + nextBuilder.startReturn().startCall(generatedGenericMethodName(next)); + nextBuilder.string(THIS_NODE_LOCAL_VAR_NAME); + addValueParameterNames(nextBuilder, next, null, true, true); + nextBuilder.end().end(); + + invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, false, invokeMethod, nextBuilder.getRoot()); } builder.tree(invokeMethod); if (next != null) { builder.end(); - - builder.startReturn().startCall(generatedGenericMethodName(next)); - builder.string(THIS_NODE_LOCAL_VAR_NAME); - addValueParameterNames(builder, next, null, true, true); - builder.end().end(); } } @@ -1209,7 +1216,7 @@ builder.startTryBlock(); } - if (specialization.getMethod() == null) { + if (specialization.getMethod() == null && !node.needsRewrites(context)) { emitEncounteredSynthetic(builder); } else if (specialization.isUninitialized() || specialization.isGeneric()) { builder.startReturn().startCall(factoryClassName(node), generatedGenericMethodName(null)); @@ -1349,7 +1356,7 @@ } builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); - ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex]; + ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex); startCallOperationMethod(builder, shortCircuitData, false); addValueParameterNames(builder, shortCircuitData, exceptionParam != null ? exceptionParam.getName() : null, false, false); diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Wed Mar 13 19:58:28 2013 +0100 @@ -39,7 +39,7 @@ private NodeData declaringNode; private List declaredChildren = new ArrayList<>(); - private final TypeSystemData typeSystem; + private TypeSystemData typeSystem; private List fields; private TypeMirror nodeType; private ParameterSpec instanceParameterSpec; @@ -50,25 +50,58 @@ private List executableTypes; private List shortCircuits; - public NodeData(TypeElement type, TypeSystemData typeSystem, String id) { + public NodeData(TypeElement type, String id) { super(type, null, null); this.nodeId = id; + } + + public NodeData(NodeData splitSource, String templateMethodName, String nodeId) { + super(splitSource.getTemplateType(), templateMethodName, null); + this.nodeId = nodeId; + this.declaringNode = splitSource.declaringNode; + this.declaredChildren = splitSource.declaredChildren; + this.typeSystem = splitSource.typeSystem; + this.nodeType = splitSource.nodeType; + this.specializations = splitSource.specializations; + this.specializationListeners = splitSource.specializationListeners; + this.guards = splitSource.guards; + this.executableTypes = splitSource.executableTypes; + this.shortCircuits = splitSource.shortCircuits; + this.fields = splitSource.fields; + } + + void setTypeSystem(TypeSystemData typeSystem) { this.typeSystem = typeSystem; } - public NodeData(NodeData copy, String templateMethodName, String nodeId) { - super(copy.getTemplateType(), templateMethodName, null); - this.nodeId = nodeId; - this.declaringNode = copy.declaringNode; - this.declaredChildren = copy.declaredChildren; - this.typeSystem = copy.typeSystem; - this.nodeType = copy.nodeType; - this.specializations = copy.specializations; - this.specializationListeners = copy.specializationListeners; - this.guards = copy.guards; - this.executableTypes = copy.executableTypes; - this.shortCircuits = copy.shortCircuits; - this.fields = copy.fields; + @Override + protected List findChildContainers() { + List sinks = new ArrayList<>(); + if (declaredChildren != null) { + sinks.addAll(declaredChildren); + } + if (typeSystem != null) { + sinks.add(typeSystem); + } + if (specializations != null) { + sinks.addAll(specializations); + } + if (specializationListeners != null) { + sinks.addAll(specializationListeners); + } + if (guards != null) { + sinks.addAll(guards); + } + if (executableTypes != null) { + sinks.addAll(executableTypes); + } + if (shortCircuits != null) { + sinks.addAll(shortCircuits); + } + if (fields != null) { + sinks.addAll(fields); + } + return sinks; } public ParameterSpec getInstanceParameterSpec() { @@ -146,9 +179,6 @@ for (SpecializationData specialization : getSpecializations()) { methods.add(specialization); - if (specialization.getShortCircuits() != null) { - methods.addAll(Arrays.asList(specialization.getShortCircuits())); - } } methods.addAll(getSpecializationListeners()); @@ -271,19 +301,52 @@ } public TypeSystemData getTypeSystem() { - if (typeSystem != null) { - return typeSystem; - } else { - return null; - } + return typeSystem; } public String dump() { - StringBuilder b = new StringBuilder(); - b.append(String.format("[id = %s, name = %s\n typeSystem = %s\n fields = %s\n types = %s\n specializations = %s\n guards = %s\n enclosing = %s\n enclosed = %s\n]", getNodeId(), - Utils.getQualifiedName(getTemplateType()), getTypeSystem(), dumpList(fields), dumpList(getExecutableTypes()), dumpList(getSpecializations()), dumpList(guards), - dumpList(getDeclaredChildren()), getParent())); - return b.toString(); + return dump(0); + } + + private String dump(int level) { + String indent = ""; + for (int i = 0; i < level; i++) { + indent += " "; + } + StringBuilder builder = new StringBuilder(); + + builder.append(String.format("%s%s {", indent, toString())); + + dumpProperty(builder, indent, "templateClass", Utils.getQualifiedName(getTemplateType())); + dumpProperty(builder, indent, "typeSystem", getTypeSystem()); + dumpProperty(builder, indent, "fields", getFields()); + dumpProperty(builder, indent, "executableTypes", getExecutableTypes()); + dumpProperty(builder, indent, "specializations", getSpecializations()); + dumpProperty(builder, indent, "guards", getGuards()); + dumpProperty(builder, indent, "messages", collectMessages()); + if (getDeclaredChildren().size() > 0) { + builder.append(String.format("\n%s children = [", indent)); + for (NodeData node : getDeclaredChildren()) { + builder.append("\n"); + builder.append(node.dump(level + 1)); + } + builder.append(String.format("\n%s ]", indent)); + } + builder.append(String.format("%s}", indent)); + return builder.toString(); + } + + private static void dumpProperty(StringBuilder b, String indent, String propertyName, Object value) { + if (value instanceof List) { + List list = (List) value; + if (!list.isEmpty()) { + b.append(String.format("\n%s %s = %s", indent, propertyName, dumpList((List) value))); + } + } else { + if (value != null) { + b.append(String.format("\n%s %s = %s", indent, propertyName, value)); + } + } } private static String dumpList(List array) { @@ -291,6 +354,12 @@ return "null"; } + if (array.isEmpty()) { + return "[]"; + } else if (array.size() == 1) { + return "[" + array.get(0).toString() + "]"; + } + StringBuilder b = new StringBuilder(); b.append("["); for (Object object : array) { diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java Wed Mar 13 19:58:28 2013 +0100 @@ -25,7 +25,9 @@ import javax.lang.model.element.*; import javax.lang.model.type.*; -public class NodeFieldData { +import com.oracle.truffle.codegen.processor.template.*; + +public class NodeFieldData extends MessageContainer { public enum FieldKind { CHILD, CHILDREN @@ -43,11 +45,10 @@ private final ExecutionKind executionKind; private NodeData nodeData; - public NodeFieldData(NodeData typeNodeData, VariableElement fieldElement, Element accessElement, AnnotationMirror childAnnotationMirror, FieldKind fieldKind, ExecutionKind executionKind) { + public NodeFieldData(VariableElement fieldElement, Element accessElement, AnnotationMirror childAnnotationMirror, FieldKind fieldKind, ExecutionKind executionKind) { this.fieldElement = fieldElement; this.accessElement = accessElement; this.childAnnotationMirror = childAnnotationMirror; - this.nodeData = typeNodeData; this.fieldKind = fieldKind; this.executionKind = executionKind; } @@ -61,12 +62,18 @@ this.nodeData = field.nodeData; } + @Override + public Element getMessageElement() { + return fieldElement; + } + public boolean isShortCircuit() { return executionKind == ExecutionKind.SHORT_CIRCUIT; } void setNode(NodeData nodeData) { this.nodeData = nodeData; + getMessages().addAll(nodeData.collectMessages()); } public VariableElement getFieldElement() { diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java --- 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 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 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 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 elements) { + private void parseMethods(final NodeData node, List 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 generics = new GenericParser(context, node).parse(elements); List specializations = new SpecializationMethodParser(context, node).parse(elements); - if (generics == null || specializations == null || node.getGuards() == null || node.getShortCircuits() == null || node.getSpecializationListeners() == null) { - return false; - } - List 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 specializations = new ArrayList<>(node.getSpecializations()); if (specializations.isEmpty()) { - return true; + return; } List 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 elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(nodeType)); List typeHierarchy = findSuperClasses(new ArrayList(), 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 executableTypes = filterExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)); - nodeData.setExecutableTypes(executableTypes); - parsedNodes.put(Utils.getQualifiedName(templateType), nodeData); - - List 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 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 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 filterExecutableTypes(List executableTypes) { @@ -657,8 +620,6 @@ } } - boolean valid = true; - List 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. 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> groupedShortCircuits = groupShortCircuits(node.getShortCircuits()); boolean valid = true; - for (NodeFieldData field : node.filterFields(null, ExecutionKind.SHORT_CIRCUIT)) { String valueName = field.getName(); List 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 assignedShortCuts = new ArrayList<>(fields.length); for (int i = 0; i < fields.length; i++) { List 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 methods, String prefix) { - boolean valid = true; + private static void verifyNamingConvention(List 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 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 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 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) { diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitParser.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitParser.java Wed Mar 13 19:58:28 2013 +0100 @@ -49,12 +49,6 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { String shortCircuitValue = Utils.getAnnotationValue(String.class, mirror, "value"); - - if (!shortCircuitValues.contains(shortCircuitValue)) { - getContext().getLog().error(method, mirror, "Invalid short circuit value %s.", shortCircuitValue); - return null; - } - return createDefaultMethodSpec(method, mirror, shortCircuitValue); } @@ -66,8 +60,11 @@ @Override public ShortCircuitData create(TemplateMethod method) { String shortCircuitValue = Utils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value"); - assert shortCircuitValue != null; - assert shortCircuitValues.contains(shortCircuitValue); + + if (!shortCircuitValues.contains(shortCircuitValue)) { + method.addError("Invalid short circuit value %s.", shortCircuitValue); + } + return new ShortCircuitData(method, shortCircuitValue); } diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Wed Mar 13 19:58:28 2013 +0100 @@ -34,8 +34,8 @@ private final boolean generic; private final boolean uninitialized; private final List exceptions; - private SpecializationGuardData[] guards; - private ShortCircuitData[] shortCircuits; + private List guards; + private List shortCircuits; private boolean useSpecializationsForGeneric = true; private NodeData node; @@ -60,15 +60,27 @@ this.generic = generic; this.uninitialized = uninitialized; this.exceptions = Collections.emptyList(); - this.guards = new SpecializationGuardData[0]; + this.guards = new ArrayList<>(); this.synthetic = synthetic; } + @Override + protected List findChildContainers() { + List sinks = new ArrayList<>(); + if (exceptions != null) { + sinks.addAll(exceptions); + } + if (guards != null) { + sinks.addAll(guards); + } + return sinks; + } + public boolean hasRewrite(ProcessorContext context) { - if (getExceptions().size() > 0) { + if (!getExceptions().isEmpty()) { return true; } - if (getGuards().length > 0) { + if (!getGuards().isEmpty()) { return true; } for (ActualParameter parameter : getParameters()) { @@ -92,7 +104,7 @@ this.node = node; } - public void setGuards(SpecializationGuardData[] guards) { + public void setGuards(List guards) { this.guards = guards; } @@ -116,15 +128,15 @@ return exceptions; } - public SpecializationGuardData[] getGuards() { + public List getGuards() { return guards; } - public void setShortCircuits(ShortCircuitData[] shortCircuits) { + public void setShortCircuits(List shortCircuits) { this.shortCircuits = shortCircuits; } - public ShortCircuitData[] getShortCircuits() { + public List getShortCircuits() { return shortCircuits; } diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationGuardData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationGuardData.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationGuardData.java Wed Mar 13 19:58:28 2013 +0100 @@ -22,20 +22,42 @@ */ package com.oracle.truffle.codegen.processor.node; +import javax.lang.model.element.*; + +import com.oracle.truffle.codegen.processor.template.*; import com.oracle.truffle.codegen.processor.typesystem.*; -public class SpecializationGuardData { +public class SpecializationGuardData extends MessageContainer { + private final SpecializationData specialization; + private final AnnotationValue value; private final String guardMethod; private final boolean onSpecialization; private final boolean onExecution; private GuardData guardDeclaration; - public SpecializationGuardData(String guardMethod, boolean onSpecialization, boolean onExecution) { + public SpecializationGuardData(SpecializationData specialization, AnnotationValue value, String guardMethod, boolean onSpecialization, boolean onExecution) { + this.specialization = specialization; this.guardMethod = guardMethod; this.onSpecialization = onSpecialization; this.onExecution = onExecution; + this.value = value; + } + + @Override + public Element getMessageElement() { + return specialization.getMessageElement(); + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return specialization.getMessageAnnotation(); + } + + @Override + public AnnotationValue getMessageAnnotationValue() { + return value; } public String getGuardMethod() { diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java Wed Mar 13 19:58:28 2013 +0100 @@ -57,19 +57,19 @@ private SpecializationData parseSpecialization(TemplateMethod method) { int order = Utils.getAnnotationValue(Integer.class, method.getMarkerAnnotation(), "order"); if (order < 0 && order != Specialization.DEFAULT_ORDER) { - getContext().getLog().error(method.getMethod(), method.getMarkerAnnotation(), "Invalid order attribute %d. The value must be >= 0 or the default value."); + method.addError("Invalid order attribute %d. The value must be >= 0 or the default value."); return null; } + AnnotationValue rewriteValue = Utils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn"); List exceptionTypes = Utils.getAnnotationValueList(TypeMirror.class, method.getMarkerAnnotation(), "rewriteOn"); List exceptionData = new ArrayList<>(); for (TypeMirror exceptionType : exceptionTypes) { - exceptionData.add(new SpecializationThrowsData(method.getMarkerAnnotation(), exceptionType)); - + SpecializationThrowsData throwsData = new SpecializationThrowsData(method.getMarkerAnnotation(), rewriteValue, exceptionType); if (!Utils.canThrowType(method.getMethod().getThrownTypes(), exceptionType)) { - getContext().getLog().error(method.getMethod(), "Method must specify a throws clause with the exception type '%s'.", Utils.getQualifiedName(exceptionType)); - return null; + throwsData.addError("Method must specify a throws clause with the exception type '%s'.", Utils.getQualifiedName(exceptionType)); } + exceptionData.add(throwsData); } Collections.sort(exceptionData, new Comparator() { @@ -81,26 +81,19 @@ }); SpecializationData specialization = new SpecializationData(method, order, exceptionData); boolean valid = true; + AnnotationValue guardsValue = Utils.getAnnotationValue(method.getMarkerAnnotation(), "guards"); List guardDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); - SpecializationGuardData[] guardData = new SpecializationGuardData[guardDefs.size()]; - for (int i = 0; i < guardData.length; i++) { + List guardData = new ArrayList<>(guardDefs.size()); + for (int i = 0; i < guardDefs.size(); i++) { String guardMethod = guardDefs.get(i); - boolean onSpecialization = true; - boolean onExecution = true; + SpecializationGuardData assignedGuard = new SpecializationGuardData(specialization, guardsValue, guardMethod, true, true); + + guardData.add(assignedGuard); - if (!onSpecialization && !onExecution) { - String message = "Either onSpecialization, onExecution or both must be enabled."; - getContext().getLog().error(method.getMethod(), message); - valid = false; - continue; - } - - guardData[i] = new SpecializationGuardData(guardMethod, onSpecialization, onExecution); - - GuardData compatibleGuard = matchSpecializationGuard(specialization, guardData[i]); + GuardData compatibleGuard = matchSpecializationGuard(specialization, assignedGuard); if (compatibleGuard != null) { - guardData[i].setGuardDeclaration(compatibleGuard); + assignedGuard.setGuardDeclaration(compatibleGuard); } else { valid = false; } @@ -136,9 +129,7 @@ } List typeDefs = createTypeDefinitions(returnTypeSpec, expectedParameterSpecs); String expectedSignature = TemplateMethodParser.createExpectedSignature(specializationGuard.getGuardMethod(), returnTypeSpec, expectedParameterSpecs, typeDefs); - AnnotationValue value = Utils.getAnnotationValue(specialization.getMarkerAnnotation(), "guards"); - getContext().getLog().error(specialization.getMethod(), specialization.getMarkerAnnotation(), value, "No guard with signature '%s' found in type system.", expectedSignature); - return null; + specializationGuard.addError("No guard with signature '%s' found in type system.", expectedSignature); } return compatibleGuard; diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationThrowsData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationThrowsData.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationThrowsData.java Wed Mar 13 19:58:28 2013 +0100 @@ -25,14 +25,18 @@ import javax.lang.model.element.*; import javax.lang.model.type.*; -public class SpecializationThrowsData { +import com.oracle.truffle.codegen.processor.template.*; +public class SpecializationThrowsData extends MessageContainer { + + private final AnnotationValue annotationValue; private final AnnotationMirror annotationMirror; private final TypeMirror javaClass; private SpecializationData specialization; - public SpecializationThrowsData(AnnotationMirror annotationMirror, TypeMirror javaClass) { + public SpecializationThrowsData(AnnotationMirror annotationMirror, AnnotationValue value, TypeMirror javaClass) { this.annotationMirror = annotationMirror; + this.annotationValue = value; this.javaClass = javaClass; } @@ -40,6 +44,21 @@ this.specialization = specialization; } + @Override + public Element getMessageElement() { + return specialization.getMessageElement(); + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return annotationMirror; + } + + @Override + public AnnotationValue getMessageAnnotationValue() { + return annotationValue; + } + public TypeMirror getJavaClass() { return javaClass; } diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Wed Mar 13 19:58:28 2013 +0100 @@ -37,12 +37,12 @@ } private final String name; - private final TypeMirror[] allowedTypes; + private final List allowedTypes; private final boolean optional; private Cardinality cardinality; private boolean indexed; - public ParameterSpec(String name, TypeMirror[] allowedTypes, boolean optional, Cardinality cardinality) { + public ParameterSpec(String name, List allowedTypes, boolean optional, Cardinality cardinality) { this.allowedTypes = allowedTypes; this.name = name; this.optional = optional; @@ -51,7 +51,7 @@ /** Type constructor. */ public ParameterSpec(String name, TypeMirror singleFixedType, boolean optional) { - this(name, new TypeMirror[]{singleFixedType}, optional, Cardinality.ONE); + this(name, Arrays.asList(singleFixedType), optional, Cardinality.ONE); } /** Type system value constructor. */ @@ -76,7 +76,7 @@ this.cardinality = cardinality; } - private static TypeMirror[] nodeTypeMirrors(NodeData nodeData) { + private static List nodeTypeMirrors(NodeData nodeData) { Set typeMirrors = new LinkedHashSet<>(); for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) { @@ -85,7 +85,7 @@ typeMirrors.add(nodeData.getTypeSystem().getGenericType()); - return typeMirrors.toArray(new TypeMirror[typeMirrors.size()]); + return new ArrayList<>(typeMirrors); } public final String getName() { @@ -100,15 +100,13 @@ return cardinality; } - public TypeMirror[] getAllowedTypes() { + public List getAllowedTypes() { return allowedTypes; } public boolean matches(TypeMirror actualType) { - for (int i = 0; i < allowedTypes.length; i++) { - TypeMirror mirror = allowedTypes[i]; + for (TypeMirror mirror : allowedTypes) { if (Utils.typeEquals(actualType, mirror)) { - return true; } } diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/Template.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/Template.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/Template.java Wed Mar 13 19:58:28 2013 +0100 @@ -29,7 +29,7 @@ import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.api.element.*; -public abstract class Template { +public abstract class Template extends MessageContainer { private final TypeElement templateType; private final String templateMethodName; @@ -43,6 +43,16 @@ this.annotation = annotation; } + @Override + public Element getMessageElement() { + return templateType; + } + + @Override + protected List findChildContainers() { + return Collections.emptyList(); + } + public String getTemplateMethodName() { return templateMethodName; } diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Wed Mar 13 19:58:28 2013 +0100 @@ -29,7 +29,7 @@ import com.oracle.truffle.codegen.processor.*; -public class TemplateMethod { +public class TemplateMethod extends MessageContainer { private String id; private final Template template; @@ -58,6 +58,22 @@ public TemplateMethod(TemplateMethod method) { this(method.id, method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters); + getMessages().addAll(method.getMessages()); + } + + @Override + public Element getMessageElement() { + return method; + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return markerAnnotation; + } + + @Override + protected List findChildContainers() { + return Collections.emptyList(); } public void setId(String id) { diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java Wed Mar 13 19:58:28 2013 +0100 @@ -96,13 +96,14 @@ mirror = Utils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType); } + E parsedMethod = parse(method, mirror); + if (method.getModifiers().contains(Modifier.PRIVATE) && emitErrors) { - getContext().getLog().error(method, "Method must not be private."); + parsedMethod.addError("Method must not be private."); valid = false; continue; } - E parsedMethod = parse(method, mirror); if (parsedMethod != null) { parsedMethods.add(parsedMethod); } else { @@ -121,6 +122,12 @@ return null; } + String id = method.getSimpleName().toString(); + AnnotationMirror idAnnotation = Utils.findAnnotationMirror(context.getEnvironment(), method, NodeId.class); + if (idAnnotation != null) { + id = Utils.getAnnotationValue(String.class, idAnnotation, "value"); + } + List typeDefs = createTypeDefinitions(methodSpecification.getReturnType(), methodSpecification.getParameters()); ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); @@ -129,16 +136,18 @@ ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, false); if (returnTypeMirror == null) { - if (isEmitErrors()) { + if (emitErrors) { + E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList())); String expectedReturnType = createTypeSignature(returnTypeSpec, typeDefs, true); String actualReturnType = Utils.getSimpleName(method.getReturnType()); String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType, createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs)); - - context.getLog().error(method, annotation, message); + invalidMethod.addError(message); + return invalidMethod; + } else { + return null; } - return null; } List parameterTypes = new ArrayList<>(); @@ -150,17 +159,14 @@ List parameters = parseParameters(parameterTypes, parameterSpecs, methodSpecification.getImplicitTypes().size()); if (parameters == null) { if (isEmitErrors()) { + E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList())); String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method), createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs)); - context.getLog().error(method, annotation, message); + invalidMethod.addError(message); + return invalidMethod; + } else { + return null; } - return null; - } - - String id = method.getSimpleName().toString(); - AnnotationMirror idAnnotation = Utils.findAnnotationMirror(context.getEnvironment(), method, NodeId.class); - if (idAnnotation != null) { - id = Utils.getAnnotationValue(String.class, idAnnotation, "value"); } return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters)); @@ -256,12 +262,12 @@ int defIndex = 0; for (ParameterSpec spec : allParams) { - TypeMirror[] allowedTypes = spec.getAllowedTypes(); - TypeMirror[] types = spec.getAllowedTypes(); - if (types != null && allowedTypes.length > 1) { + List allowedTypes = spec.getAllowedTypes(); + List types = spec.getAllowedTypes(); + if (types != null && allowedTypes.size() > 1) { TypeDef foundDef = null; for (TypeDef def : typeDefs) { - if (Arrays.equals(allowedTypes, def.getTypes())) { + if (allowedTypes.equals(def.getTypes())) { foundDef = def; break; } @@ -281,11 +287,11 @@ protected static class TypeDef { - private final TypeMirror[] types; + private final List types; private final String name; private final List parameters = new ArrayList<>(); - public TypeDef(TypeMirror[] types, String name) { + public TypeDef(List types, String name) { this.types = types; this.name = name; } @@ -294,7 +300,7 @@ return parameters; } - public TypeMirror[] getTypes() { + public List getTypes() { return types; } @@ -363,7 +369,7 @@ private static String createTypeSignature(ParameterSpec spec, List typeDefs, boolean typeOnly) { StringBuilder builder = new StringBuilder(); - if (spec.getAllowedTypes().length > 1) { + if (spec.getAllowedTypes().size() > 1) { TypeDef foundTypeDef = null; for (TypeDef typeDef : typeDefs) { if (typeDef.getParameters().contains(spec)) { @@ -374,8 +380,8 @@ if (foundTypeDef != null) { builder.append("<" + foundTypeDef.getName() + ">"); } - } else if (spec.getAllowedTypes().length == 1) { - builder.append(Utils.getSimpleName(spec.getAllowedTypes()[0])); + } else if (spec.getAllowedTypes().size() == 1) { + builder.append(Utils.getSimpleName(spec.getAllowedTypes().get(0))); } else { builder.append("void"); } diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java Wed Mar 13 19:58:28 2013 +0100 @@ -43,9 +43,8 @@ return extensionParser; } - protected boolean verifyExclusiveMethodAnnotation(TypeElement type, Class... annotationTypes) { - boolean valid = true; - List methods = ElementFilter.methodsIn(type.getEnclosedElements()); + protected void verifyExclusiveMethodAnnotation(Template template, Class... annotationTypes) { + List methods = ElementFilter.methodsIn(template.getTemplateType().getEnclosedElements()); for (ExecutableElement method : methods) { List foundAnnotations = new ArrayList<>(); for (int i = 0; i < annotationTypes.length; i++) { @@ -61,34 +60,9 @@ annotationNames.add("@" + Utils.getSimpleName(mirror.getAnnotationType())); } - for (AnnotationMirror mirror : foundAnnotations) { - context.getLog().error(method, mirror, "Non exclusive usage of annotations %s.", annotationNames); - } - valid = false; + template.addError("Non exclusive usage of annotations %s.", annotationNames); } } - return valid; - } - - protected boolean verifyTemplateType(TypeElement template, AnnotationMirror annotation) { - // annotation type on class path!? - boolean valid = true; - TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName()); - if (annotationTypeElement == null) { - log.error(template, annotation, "Required class " + getAnnotationType().getName() + " is not on the classpath."); - valid = false; - } - if (template.getModifiers().contains(Modifier.PRIVATE)) { - log.error(template, annotation, "The annotated class must have at least package protected visibility."); - valid = false; - } - - if (template.getModifiers().contains(Modifier.FINAL)) { - log.error(template, annotation, "The annotated class must not be final."); - valid = false; - } - - return valid; } } diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java Wed Mar 13 19:58:28 2013 +0100 @@ -41,7 +41,7 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - TypeData targetType = findTypeByMethodName(method, mirror, "as"); + TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "as"); if (targetType == null) { return null; } @@ -54,7 +54,7 @@ @Override public TypeCastData create(TemplateMethod method) { - TypeData targetType = findTypeByMethodName(method.getMethod(), method.getMarkerAnnotation(), "as"); + TypeData targetType = findTypeByMethodName(method, "as"); ActualParameter parameter = method.findParameter("valueValue"); return new TypeCastData(method, parameter.getActualTypeData(getTypeSystem()), targetType); } diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java Wed Mar 13 19:58:28 2013 +0100 @@ -41,7 +41,7 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - TypeData targetType = findTypeByMethodName(method, mirror, "is"); + TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "is"); if (targetType == null) { return null; } @@ -54,7 +54,7 @@ @Override public TypeCheckData create(TemplateMethod method) { - TypeData checkedType = findTypeByMethodName(method.getMethod(), method.getMarkerAnnotation(), "is"); + TypeData checkedType = findTypeByMethodName(method, "is"); assert checkedType != null; ActualParameter parameter = method.findParameter("valueValue"); assert parameter != null; diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java Wed Mar 13 19:58:28 2013 +0100 @@ -30,21 +30,38 @@ import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.template.*; -public class TypeData extends Template { +public class TypeData extends MessageContainer { - protected TypeSystemData typeSystem; + private final TypeSystemData typeSystem; + private final AnnotationValue annotationValue; private final TypeMirror primitiveType; private final TypeMirror boxedType; private final List typeCasts = new ArrayList<>(); private final List typeChecks = new ArrayList<>(); - public TypeData(TypeElement templateType, AnnotationMirror annotation, TypeMirror primitiveType, TypeMirror boxedType) { - super(templateType, null, annotation); + public TypeData(TypeSystemData typeSystem, AnnotationValue value, TypeMirror primitiveType, TypeMirror boxedType) { + this.typeSystem = typeSystem; + this.annotationValue = value; this.primitiveType = primitiveType; this.boxedType = boxedType; } + @Override + public Element getMessageElement() { + return typeSystem.getMessageElement(); + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return typeSystem.getMessageAnnotation(); + } + + @Override + public AnnotationValue getMessageAnnotationValue() { + return annotationValue; + } + void addTypeCast(TypeCastData typeCast) { this.typeCasts.add(typeCast); } diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java Wed Mar 13 19:58:28 2013 +0100 @@ -167,8 +167,8 @@ CodeTreeBuilder builder = method.createBuilder(); builder.startReturn(); - if (typeSystem.getTypes().length > 0) { - builder.typeLiteral(typeSystem.getTypes()[0].getBoxedType()); + if (!typeSystem.getTypes().isEmpty()) { + builder.typeLiteral(typeSystem.getTypes().get(0).getBoxedType()); } else { builder.null_(); } diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java Wed Mar 13 19:58:28 2013 +0100 @@ -32,35 +32,42 @@ public class TypeSystemData extends Template { - private final TypeData[] types; - private final TypeMirror[] primitiveTypeMirrors; - private final TypeMirror[] boxedTypeMirrors; + private List types; + private List primitiveTypeMirrors = new ArrayList<>(); + private List boxedTypeMirrors = new ArrayList<>(); - private final TypeMirror genericType; + private TypeMirror genericType; + private TypeData voidType; + + public TypeSystemData(TypeElement templateType, AnnotationMirror annotation) { + super(templateType, null, annotation); + } - private final TypeData voidType; + void setTypes(List types) { + this.types = types; + if (types != null) { + for (TypeData typeData : types) { + primitiveTypeMirrors.add(typeData.getPrimitiveType()); + boxedTypeMirrors.add(typeData.getBoxedType()); + } + } + } - public TypeSystemData(TypeElement templateType, AnnotationMirror annotation, TypeData[] types, TypeMirror genericType, TypeData voidType) { - super(templateType, null, annotation); - this.types = types; + void setGenericType(TypeMirror genericType) { this.genericType = genericType; + } + + void setVoidType(TypeData voidType) { this.voidType = voidType; - this.primitiveTypeMirrors = new TypeMirror[types.length]; - for (int i = 0; i < types.length; i++) { - primitiveTypeMirrors[i] = types[i].getPrimitiveType(); - } + } - this.boxedTypeMirrors = new TypeMirror[types.length]; - for (int i = 0; i < types.length; i++) { - boxedTypeMirrors[i] = types[i].getBoxedType(); + @Override + protected List findChildContainers() { + List sinks = new ArrayList<>(); + if (types != null) { + sinks.addAll(types); } - - for (TypeData type : types) { - type.typeSystem = this; - } - if (voidType != null) { - voidType.typeSystem = this; - } + return sinks; } public boolean isGeneric(TypeMirror type) { @@ -71,16 +78,16 @@ return voidType; } - public TypeData[] getTypes() { - return types; + public List getBoxedTypeMirrors() { + return boxedTypeMirrors; } - public TypeMirror[] getPrimitiveTypeMirrors() { + public List getPrimitiveTypeMirrors() { return primitiveTypeMirrors; } - public TypeMirror[] getBoxedTypeMirrors() { - return boxedTypeMirrors; + public List getTypes() { + return types; } public TypeMirror getGenericType() { @@ -88,7 +95,7 @@ } public TypeData getGenericTypeData() { - TypeData result = types[types.length - 1]; + TypeData result = types.get(types.size() - 1); assert result.getBoxedType() == genericType; return result; } @@ -111,7 +118,7 @@ if (index == -1) { return null; } - return types[index]; + return types.get(index); } public int findType(TypeData typeData) { @@ -119,8 +126,8 @@ } public int findType(TypeMirror type) { - for (int i = 0; i < types.length; i++) { - if (Utils.typeEquals(types[i].getPrimitiveType(), type)) { + for (int i = 0; i < types.size(); i++) { + if (Utils.typeEquals(types.get(i).getPrimitiveType(), type)) { return i; } } @@ -129,7 +136,7 @@ @Override public String toString() { - return getClass().getSimpleName() + "[template = " + Utils.getSimpleName(getTemplateType()) + ", types = " + Arrays.toString(types) + "]"; + return getClass().getSimpleName() + "[template = " + Utils.getSimpleName(getTemplateType()) + ", types = " + types + "]"; } } diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java Wed Mar 13 19:58:28 2013 +0100 @@ -43,18 +43,24 @@ return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; } - protected TypeData findTypeByMethodName(ExecutableElement method, AnnotationMirror annotationMirror, String prefix) { - String methodName = method.getSimpleName().toString(); + protected TypeData findTypeByMethodName(String methodName, String prefix) { + String typeName = methodName.substring(prefix.length(), methodName.length()); + TypeData type = getTypeSystem().findType(typeName); + return type; + } + + protected TypeData findTypeByMethodName(TemplateMethod method, String prefix) { + String methodName = method.getMethodName(); if (!methodName.startsWith(prefix)) { - String annotationName = Utils.getSimpleName(annotationMirror.getAnnotationType()); - getContext().getLog().error(method, "Methods annotated with %s must match the pattern '%s'.", annotationName, String.format("%s${typeName}", prefix)); + String annotationName = Utils.getSimpleName(method.getMessageAnnotation().getAnnotationType()); + method.addError("Methods annotated with %s must match the pattern '%s'.", annotationName, String.format("%s${typeName}", prefix)); return null; } String typeName = methodName.substring(prefix.length(), methodName.length()); TypeData type = getTypeSystem().findType(typeName); if (type == null) { String annotationName = TypeSystem.class.getSimpleName(); - getContext().getLog().error(method, "Type '%s' is not declared in this @%s.", typeName, annotationName); + method.addError("Type '%s' is not declared in this @%s.", typeName, annotationName); return null; } diff -r cb70ed101b5f -r 0905d796944a graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java Wed Mar 13 11:32:43 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java Wed Mar 13 19:58:28 2013 +0100 @@ -52,27 +52,39 @@ protected TypeSystemData parse(Element element, AnnotationMirror mirror) { TypeElement templateType = (TypeElement) element; AnnotationMirror templateTypeAnnotation = mirror; + TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation); - if (!verifyTemplateType(templateType, templateTypeAnnotation)) { - return null; + // annotation type on class path!? + TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName()); + if (annotationTypeElement == null) { + typeSystem.addError("Required class %s is not on the classpath.", getAnnotationType().getName()); + } + if (templateType.getModifiers().contains(Modifier.PRIVATE)) { + typeSystem.addError("A @%s must have at least package protected visibility.", getAnnotationType().getName()); } - TypeData[] types = parseTypes(templateType, templateTypeAnnotation); - if (types == null) { - return null; + if (templateType.getModifiers().contains(Modifier.FINAL)) { + typeSystem.addError("The @%s must not be final.", getAnnotationType().getName()); + } + if (typeSystem.hasErrors()) { + return typeSystem; + } + + typeSystem.setTypes(parseTypes(typeSystem)); + if (typeSystem.getTypes() == null) { + return typeSystem; } TypeMirror genericType = context.getType(Object.class); - TypeData voidType = new TypeData(templateType, templateTypeAnnotation, context.getType(void.class), context.getType(Void.class)); - - TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation, types, genericType, voidType); + TypeData voidType = new TypeData(typeSystem, null, context.getType(void.class), context.getType(Void.class)); - if (!verifyExclusiveMethodAnnotation(templateType, TypeCast.class, TypeCheck.class)) { - return null; - } + typeSystem.setGenericType(genericType); + typeSystem.setVoidType(voidType); + + verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class); List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType)); - typeSystem.setExtensionElements(getExtensionParser().parseAll(templateType, elements)); + typeSystem.setExtensionElements(getExtensionParser().parseAll(typeSystem, elements)); if (typeSystem.getExtensionElements() != null) { elements.addAll(typeSystem.getExtensionElements()); } @@ -81,7 +93,7 @@ List checks = new TypeCheckParser(context, typeSystem).parse(elements); if (casts == null || checks == null) { - return null; + return typeSystem; } for (TypeCheckData check : checks) { @@ -92,24 +104,15 @@ cast.getTargetType().addTypeCast(cast); } - if (!verifyGenericTypeChecksAndCasts(types)) { - return null; - } - - if (!verifyMethodSignatures(element, types)) { - return null; - } - - if (!verifyNamesUnique(templateType, templateTypeAnnotation, types)) { - return null; - } + verifyGenericTypeChecksAndCasts(typeSystem); + verifyMethodSignatures(typeSystem); + verifyNamesUnique(typeSystem); return typeSystem; } - private boolean verifyGenericTypeChecksAndCasts(TypeData[] types) { - boolean valid = true; - for (TypeData type : types) { + private static void verifyGenericTypeChecksAndCasts(TypeSystemData typeSystem) { + for (TypeData type : typeSystem.getTypes()) { if (!type.getTypeChecks().isEmpty()) { boolean hasGeneric = false; for (TypeCheckData typeCheck : type.getTypeChecks()) { @@ -119,10 +122,9 @@ } } if (!hasGeneric) { - log.error(type.getTypeSystem().getTemplateType(), "No generic but specific @%s method %s for type %s specified. " - + "Specify a generic @%s method with parameter type %s to resolve this.", TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type), - Utils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(), Object.class.getSimpleName()); - valid = false; + type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.", + TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(), + Object.class.getSimpleName()); } } if (!type.getTypeCasts().isEmpty()) { @@ -134,60 +136,55 @@ } } if (!hasGeneric) { - log.error(type.getTypeSystem().getTemplateType(), "No generic but specific @%s method %s for type %s specified. " - + "Specify a generic @%s method with parameter type %s to resolve this.", TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type), - Utils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(), Object.class.getSimpleName()); - valid = false; + type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.", + TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(), + Object.class.getSimpleName()); } } } - return valid; } - private TypeData[] parseTypes(TypeElement templateType, AnnotationMirror templateTypeAnnotation) { - List typeMirrors = Utils.getAnnotationValueList(TypeMirror.class, templateTypeAnnotation, "value"); - if (typeMirrors.size() == 0) { - log.error(templateType, templateTypeAnnotation, "At least one type must be defined."); - return null; + private List parseTypes(TypeSystemData typeSystem) { + List types = new ArrayList<>(); + List typeMirrors = Utils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value"); + if (typeMirrors.isEmpty()) { + typeSystem.addError("At least one type must be defined."); + return types; } - final AnnotationValue annotationValue = Utils.getAnnotationValue(templateTypeAnnotation, "value"); + final AnnotationValue annotationValue = Utils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "value"); final TypeMirror objectType = context.getType(Object.class); - List types = new ArrayList<>(); for (TypeMirror primitiveType : typeMirrors) { + TypeMirror boxedType = Utils.boxType(context, primitiveType); + TypeData typeData = new TypeData(typeSystem, annotationValue, primitiveType, boxedType); if (isPrimitiveWrapper(primitiveType)) { - log.error(templateType, templateTypeAnnotation, annotationValue, "Types must not contain primitive wrapper types."); - continue; + typeData.addError("Types must not contain primitive wrapper types."); } - TypeMirror boxedType = Utils.boxType(context, primitiveType); - if (Utils.typeEquals(boxedType, objectType)) { - log.error(templateType, templateTypeAnnotation, annotationValue, "Types must not contain the generic type java.lang.Object."); - continue; + typeData.addError("Types must not contain the generic type java.lang.Object."); } - types.add(new TypeData(templateType, templateTypeAnnotation, primitiveType, boxedType)); + types.add(typeData); } - verifyTypeOrder(templateType, templateTypeAnnotation, annotationValue, types); + verifyTypeOrder(types); - types.add(new TypeData(templateType, templateTypeAnnotation, objectType, objectType)); + types.add(new TypeData(typeSystem, annotationValue, objectType, objectType)); - return types.toArray(new TypeData[types.size()]); + return types; } - private void verifyTypeOrder(TypeElement templateType, AnnotationMirror templateTypeAnnotation, AnnotationValue annotationValue, List types) { + private static void verifyTypeOrder(List types) { Map> invalidTypes = new HashMap<>(); for (int i = types.size() - 1; i >= 0; i--) { TypeData typeData = types.get(i); TypeMirror type = typeData.getBoxedType(); if (invalidTypes.containsKey(Utils.getQualifiedName(type))) { - log.error(templateType, templateTypeAnnotation, annotationValue, "Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", - invalidTypes.get(Utils.getQualifiedName(type)), Utils.getQualifiedName(type)); + typeData.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(Utils.getQualifiedName(type)), Utils.getQualifiedName(type)); } List nextInvalidTypes = Utils.getQualifiedSuperTypeNames(Utils.fromTypeMirror(type)); nextInvalidTypes.add(getQualifiedName(type)); @@ -216,19 +213,18 @@ return false; } - private boolean verifyMethodSignatures(Element element, TypeData[] types) { + private void verifyMethodSignatures(TypeSystemData typeSystem) { Set generatedIsMethodNames = new HashSet<>(); Set generatedAsMethodNames = new HashSet<>(); Set generatedExpectMethodNames = new HashSet<>(); - for (TypeData typeData : types) { + for (TypeData typeData : typeSystem.getTypes()) { generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData)); generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData)); generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData)); } - boolean valid = true; - List methods = ElementFilter.methodsIn(element.getEnclosedElements()); + List methods = ElementFilter.methodsIn(typeSystem.getTemplateType().getEnclosedElements()); for (ExecutableElement method : methods) { if (method.getModifiers().contains(Modifier.PRIVATE)) { // will not conflict overridden methods @@ -238,51 +234,48 @@ } String methodName = method.getSimpleName().toString(); if (generatedIsMethodNames.contains(methodName)) { - valid &= verifyIsMethod(method); + verifyIsMethod(typeSystem, method); } else if (generatedAsMethodNames.contains(methodName)) { - valid &= verifyAsMethod(method); + verifyAsMethod(typeSystem, method); } else if (generatedExpectMethodNames.contains(methodName)) { - valid &= verifyExpectMethod(method); + verifyExpectMethod(typeSystem); } } - return valid; } - private boolean verifyIsMethod(ExecutableElement method) { + private boolean verifyIsMethod(TypeSystemData typeSystem, ExecutableElement method) { AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCheck.class); if (mirror == null) { - log.error(method, "Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName()); + typeSystem.addError("Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName()); return false; } return true; } - private boolean verifyAsMethod(ExecutableElement method) { + private boolean verifyAsMethod(TypeSystemData typeSystem, ExecutableElement method) { AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCast.class); if (mirror == null) { - log.error(method, "Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName()); + typeSystem.addError("Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName()); return false; } return true; } - private boolean verifyExpectMethod(ExecutableElement method) { - log.error(method, "Method starting with the pattern expect${typeName} must not be declared manually."); + private static boolean verifyExpectMethod(TypeSystemData typeSystem) { + typeSystem.addError("Method starting with the pattern expect${typeName} must not be declared manually."); return false; } - private boolean verifyNamesUnique(TypeElement templateType, AnnotationMirror templateTypeAnnotation, TypeData[] types) { - boolean valid = true; - for (int i = 0; i < types.length; i++) { - for (int j = i + 1; j < types.length; j++) { - String name1 = Utils.getSimpleName(types[i].getBoxedType()); - String name2 = Utils.getSimpleName(types[j].getBoxedType()); + private static void verifyNamesUnique(TypeSystemData typeSystem) { + List types = typeSystem.getTypes(); + for (int i = 0; i < types.size(); i++) { + for (int j = i + 1; j < types.size(); j++) { + String name1 = Utils.getSimpleName(types.get(i).getBoxedType()); + String name2 = Utils.getSimpleName(types.get(j).getBoxedType()); if (name1.equalsIgnoreCase(name2)) { - log.error(templateType, templateTypeAnnotation, "Two types result in the same name: %s, %s.", name1, name2); - valid = false; + typeSystem.addError("Two types result in the same name: %s, %s.", name1, name2); } } } - return valid; } }