# HG changeset patch # User Christian Humer # Date 1366452982 -7200 # Node ID 97ad6d3e75578927e0ea4246b027c22b3a94c024 # Parent 1964871a642daeb2fe9664600b960bea6f536478 Codegen API changes. Executed child nodes are now defined using @NodeChildren instead of fields. diff -r 1964871a642d -r 97ad6d3e7557 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java Sat Apr 20 12:16:22 2013 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.codegen; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE}) +public @interface NodeChild { + + String value() default ""; + + Class type() default NodeClass.InheritNode.class; + + String[] executeWith() default {}; +} diff -r 1964871a642d -r 97ad6d3e7557 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChildren.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChildren.java Sat Apr 20 12:16:22 2013 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.codegen; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE}) +public @interface NodeChildren { + + NodeChild[] value() default {}; + +} diff -r 1964871a642d -r 97ad6d3e7557 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeClass.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeClass.java Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeClass.java Sat Apr 20 12:16:22 2013 +0200 @@ -30,6 +30,11 @@ @Target({ElementType.TYPE}) public @interface NodeClass { - Class value(); + public static final class InheritNode extends Node { + } + + Class value() default InheritNode.class; + + boolean splitByMethodName() default false; } diff -r 1964871a642d -r 97ad6d3e7557 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCast.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCast.java Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCast.java Sat Apr 20 12:16:22 2013 +0200 @@ -24,11 +24,6 @@ import java.lang.annotation.*; -/** - * - * - * - */ @Retention(RetentionPolicy.CLASS) @Target({ElementType.METHOD}) public @interface TypeCast { diff -r 1964871a642d -r 97ad6d3e7557 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 Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java Sat Apr 20 12:16:22 2013 +0200 @@ -43,8 +43,8 @@ private final TypeMirror nodeArray; private final TypeMirror unexpectedValueException; private final TypeMirror frame; - private final TypeMirror stableAnnotation; - private final TypeMirror contentStableAnnotation; + private final DeclaredType childAnnotation; + private final DeclaredType childrenAnnotation; private final TypeMirror typeConversion; private final TypeMirror truffleIntrinsics; @@ -55,8 +55,8 @@ nodeArray = context.getEnvironment().getTypeUtils().getArrayType(node); unexpectedValueException = getRequired(context, UnexpectedResultException.class); frame = getRequired(context, VirtualFrame.class); - stableAnnotation = getRequired(context, Child.class); - contentStableAnnotation = getRequired(context, Children.class); + childAnnotation = getRequired(context, Child.class); + childrenAnnotation = getRequired(context, Children.class); typeConversion = getRequired(context, TypeConversion.class); truffleIntrinsics = getRequired(context, TruffleIntrinsics.class); } @@ -73,12 +73,12 @@ return false; } - private TypeMirror getRequired(ProcessorContext context, Class clazz) { + private DeclaredType getRequired(ProcessorContext context, Class clazz) { TypeMirror type = context.getType(clazz); if (type == null) { errors.add(String.format("Could not find required type: %s", clazz.getSimpleName())); } - return type; + return (DeclaredType) type; } public TypeMirror getTruffleIntrinsics() { @@ -105,11 +105,11 @@ return unexpectedValueException; } - public TypeMirror getStableAnnotation() { - return stableAnnotation; + public DeclaredType getChildAnnotation() { + return childAnnotation; } - public TypeMirror getContentStableAnnotation() { - return contentStableAnnotation; + public DeclaredType getChildrenAnnotation() { + return childrenAnnotation; } } diff -r 1964871a642d -r 97ad6d3e7557 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Sat Apr 20 12:16:22 2013 +0200 @@ -32,6 +32,7 @@ import javax.lang.model.util.*; import com.oracle.truffle.codegen.processor.ast.*; +import com.oracle.truffle.codegen.processor.ast.CodeTypeMirror.DeclaredCodeTypeMirror; import com.oracle.truffle.codegen.processor.compiler.*; /** @@ -63,17 +64,20 @@ return types; } + public static DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) { + return new DeclaredCodeTypeMirror(typeElem, Arrays.asList(typeArgs)); + } + public static List collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element, Class annotationClass) { - List result = Utils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName); + List result = new ArrayList<>(); + if (markerAnnotation != null) { + result.addAll(Utils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName)); + } AnnotationMirror explicit = Utils.findAnnotationMirror(context.getEnvironment(), element, annotationClass); if (explicit != null) { result.add(explicit); } - - for (AnnotationMirror mirror : result) { - assert Utils.typeEquals(mirror.getAnnotationType(), context.getType(annotationClass)); - } return result; } @@ -319,6 +323,8 @@ return getSimpleName(mirror); case ERROR: throw new CompileErrorException("Type error " + mirror); + case NONE: + return "$none"; default: throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror); } @@ -371,7 +377,7 @@ return null; } - private static List getElementHierarchy(Element e) { + public static List getElementHierarchy(Element e) { List elements = new ArrayList<>(); elements.add(e); @@ -589,7 +595,7 @@ @Override public Object visitEnumConstant(VariableElement c, Void p) { - return c.getConstantValue(); + return c; } @Override @@ -772,11 +778,7 @@ public static Modifier getVisibility(Set modifier) { for (Modifier mod : modifier) { - if (mod == Modifier.PUBLIC) { - return mod; - } else if (mod == Modifier.PRIVATE) { - return mod; - } else if (mod == Modifier.PROTECTED) { + if (mod == Modifier.PUBLIC || mod == Modifier.PRIVATE || mod == Modifier.PROTECTED) { return mod; } } @@ -813,4 +815,20 @@ return getQualifiedName(actualType).equals("java.lang.Object"); } + public static boolean isFieldAccessible(Element element, VariableElement variable) { + TypeElement type = Utils.findNearestEnclosingType(element); + TypeElement varType = Utils.findNearestEnclosingType(variable); + + while (type != null) { + if (typeEquals(type.asType(), varType.asType())) { + return true; + } + if (type.getSuperclass() != null) { + type = Utils.fromTypeMirror(type.getSuperclass()); + } else { + type = null; + } + } + return false; + } } diff -r 1964871a642d -r 97ad6d3e7557 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java Sat Apr 20 12:16:22 2013 +0200 @@ -215,7 +215,7 @@ copy.addAnnotationMirror(mirror); } for (VariableElement var : method.getParameters()) { - copy.addParameter(var); + copy.addParameter(CodeVariableElement.clone(var)); } for (Element element : method.getEnclosedElements()) { copy.add(element); diff -r 1964871a642d -r 97ad6d3e7557 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java Sat Apr 20 12:16:22 2013 +0200 @@ -63,11 +63,17 @@ public static class DeclaredCodeTypeMirror extends CodeTypeMirror implements DeclaredType { - private final CodeTypeElement clazz; + private final TypeElement clazz; + private final List typeArguments; - public DeclaredCodeTypeMirror(CodeTypeElement clazz) { + public DeclaredCodeTypeMirror(TypeElement clazz) { + this(clazz, Collections. emptyList()); + } + + public DeclaredCodeTypeMirror(TypeElement clazz, List typeArguments) { super(TypeKind.DECLARED); this.clazz = clazz; + this.typeArguments = typeArguments; } @Override @@ -82,7 +88,7 @@ @Override public List getTypeArguments() { - return Collections.emptyList(); + return typeArguments; } @Override diff -r 1964871a642d -r 97ad6d3e7557 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java Sat Apr 20 12:16:22 2013 +0200 @@ -123,9 +123,9 @@ writeClassImpl(e); } - private String useImport(TypeMirror type) { + private String useImport(Element enclosedType, TypeMirror type) { if (imports != null) { - return imports.useImport(type); + return imports.createTypeReference(enclosedType, type); } else { return Utils.getSimpleName(type); } @@ -133,7 +133,7 @@ private void writeClassImpl(CodeTypeElement e) { for (AnnotationMirror annotation : e.getAnnotationMirrors()) { - visitAnnotation(annotation); + visitAnnotation(e, annotation); writeLn(); } @@ -145,12 +145,12 @@ } write(e.getSimpleName()); if (e.getSuperclass() != null && !getQualifiedName(e.getSuperclass()).equals("java.lang.Object")) { - write(" extends ").write(useImport(e.getSuperclass())); + write(" extends ").write(useImport(e, e.getSuperclass())); } if (e.getImplements().size() > 0) { write(" implements "); for (int i = 0; i < e.getImplements().size(); i++) { - write(useImport(e.getImplements().get(i))); + write(useImport(e, e.getImplements().get(i))); if (i < e.getImplements().size() - 1) { write(", "); } @@ -255,8 +255,8 @@ Element parent = f.getEnclosingElement(); for (AnnotationMirror annotation : f.getAnnotationMirrors()) { - visitAnnotation(annotation); - writeLn(); + visitAnnotation(f, annotation); + write(" "); } CodeTree init = null; @@ -275,7 +275,7 @@ } } else { writeModifiers(f.getModifiers()); - write(useImport(f.asType())); + write(useImport(f, f.asType())); if (f.getEnclosingElement().getKind() == ElementKind.METHOD) { ExecutableElement method = (ExecutableElement) f.getEnclosingElement(); @@ -294,8 +294,8 @@ return null; } - public void visitAnnotation(AnnotationMirror e) { - write("@").write(useImport(e.getAnnotationType())); + public void visitAnnotation(Element enclosedElement, AnnotationMirror e) { + write("@").write(useImport(enclosedElement, e.getAnnotationType())); if (!e.getElementValues().isEmpty()) { write("("); @@ -303,7 +303,7 @@ Map values = e.getElementValues(); if (defaultElement != null && values.size() == 1 && values.get(defaultElement) != null) { - visitAnnotationValue(values.get(defaultElement)); + visitAnnotationValue(enclosedElement, values.get(defaultElement)); } else { Set methodsSet = values.keySet(); List methodsList = new ArrayList<>(); @@ -327,7 +327,7 @@ AnnotationValue value = values.get(method); write(method.getSimpleName().toString()); write(" = "); - visitAnnotationValue(value); + visitAnnotationValue(enclosedElement, value); if (i < methodsList.size() - 1) { write(", "); @@ -339,12 +339,18 @@ } } - public void visitAnnotationValue(AnnotationValue e) { - e.accept(new AnnotationValueWriterVisitor(), null); + public void visitAnnotationValue(Element enclosedElement, AnnotationValue e) { + e.accept(new AnnotationValueWriterVisitor(enclosedElement), null); } private class AnnotationValueWriterVisitor extends AbstractAnnotationValueVisitor7 { + private final Element enclosedElement; + + public AnnotationValueWriterVisitor(Element enclosedElement) { + this.enclosedElement = enclosedElement; + } + @Override public Void visitBoolean(boolean b, Void p) { write(Boolean.toString(b)); @@ -403,14 +409,14 @@ @Override public Void visitType(TypeMirror t, Void p) { - write(useImport(t)); + write(useImport(enclosedElement, t)); write(".class"); return null; } @Override public Void visitEnumConstant(VariableElement c, Void p) { - write(useImport(c.asType())); + write(useImport(enclosedElement, c.asType())); write("."); write(c.getSimpleName().toString()); return null; @@ -418,7 +424,7 @@ @Override public Void visitAnnotation(AnnotationMirror a, Void p) { - AbstractCodeWriter.this.visitAnnotation(a); + AbstractCodeWriter.this.visitAnnotation(enclosedElement, a); return null; } @@ -427,7 +433,7 @@ write("{"); for (int i = 0; i < vals.size(); i++) { AnnotationValue value = vals.get(i); - AbstractCodeWriter.this.visitAnnotationValue(value); + AbstractCodeWriter.this.visitAnnotationValue(enclosedElement, value); if (i < vals.size() - 1) { write(", "); } @@ -459,14 +465,14 @@ @Override public Void visitExecutable(CodeExecutableElement e, Void p) { for (AnnotationMirror annotation : e.getAnnotationMirrors()) { - visitAnnotation(annotation); + visitAnnotation(e, annotation); writeLn(); } writeModifiers(e.getModifiers()); if (e.getReturnType() != null) { - write(useImport(e.getReturnType())); + write(useImport(e, e.getReturnType())); write(" "); } write(e.getSimpleName()); @@ -485,7 +491,7 @@ if (throwables.size() > 0) { write(" throws "); for (int i = 0; i < throwables.size(); i++) { - write(useImport(throwables.get(i))); + write(useImport(e, throwables.get(i))); if (i < throwables.size() - 1) { write(", "); } @@ -549,20 +555,20 @@ break; case STATIC_FIELD_REFERENCE: if (e.getString() != null) { - write(imports.useStaticFieldImport(e.getType(), e.getString())); + write(imports.createStaticFieldReference(e, e.getType(), e.getString())); } else { write("null"); } break; case STATIC_METHOD_REFERENCE: if (e.getString() != null) { - write(imports.useStaticMethodImport(e.getType(), e.getString())); + write(imports.createStaticMethodReference(e, e.getType(), e.getString())); } else { write("null"); } break; case TYPE: - write(useImport(e.getType())); + write(useImport(e, e.getType())); break; default: assert false; diff -r 1964871a642d -r 97ad6d3e7557 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 Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java Sat Apr 20 12:16:22 2013 +0200 @@ -29,8 +29,8 @@ import javax.lang.model.type.*; import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; import com.oracle.truffle.codegen.processor.template.*; -import com.oracle.truffle.codegen.processor.template.ParameterSpec.*; import com.oracle.truffle.codegen.processor.typesystem.*; public class ExecutableTypeMethodParser extends NodeMethodParser { @@ -46,7 +46,7 @@ MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null); spec.setVariableRequiredArguments(true); ParameterSpec other = new ParameterSpec("other", nodeTypeMirrors(getNode())); - other.setCardinality(Cardinality.MULTIPLE); + other.setCardinality(Cardinality.MANY); other.setSignature(true); other.setIndexed(true); spec.addRequired(other); diff -r 1964871a642d -r 97ad6d3e7557 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java Sat Apr 20 12:16:22 2013 +0200 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.node; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.template.*; + +public class NodeChildData extends MessageContainer { + + public enum Cardinality { + ONE, MANY; + + public boolean isMany() { + return this == MANY; + } + + public boolean isOne() { + return this == ONE; + } + } + + public enum ExecutionKind { + DEFAULT, SHORT_CIRCUIT + } + + private final Element sourceElement; + private final AnnotationMirror sourceAnnotationMirror; + + private final String name; + private final TypeMirror type; + private final Element accessElement; + + private final Cardinality cardinality; + private final ExecutionKind executionKind; + private NodeData nodeData; + + public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, Element accessElement, Cardinality cardinality, ExecutionKind executionKind) { + this.sourceElement = sourceElement; + this.sourceAnnotationMirror = sourceMirror; + this.name = name; + this.type = nodeType; + this.accessElement = accessElement; + this.cardinality = cardinality; + this.executionKind = executionKind; + } + + @Override + public Element getMessageElement() { + return sourceElement; + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return sourceAnnotationMirror; + } + + public boolean isShortCircuit() { + return executionKind == ExecutionKind.SHORT_CIRCUIT; + } + + void setNode(NodeData nodeData) { + this.nodeData = nodeData; + getMessages().addAll(nodeData.collectMessages()); + } + + public Element getAccessElement() { + return accessElement; + } + + public TypeMirror getNodeType() { + return type; + } + + public Cardinality getCardinality() { + return cardinality; + } + + public ExecutionKind getExecutionKind() { + return executionKind; + } + + public NodeData getNodeData() { + return nodeData; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", execution=" + executionKind + ", node=" + getNodeData() + "]"; + } + +} diff -r 1964871a642d -r 97ad6d3e7557 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 Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Sat Apr 20 12:16:22 2013 +0200 @@ -34,8 +34,8 @@ import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.ast.*; -import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind; -import com.oracle.truffle.codegen.processor.node.NodeFieldData.FieldKind; +import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; +import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; import com.oracle.truffle.codegen.processor.template.*; import com.oracle.truffle.codegen.processor.typesystem.*; @@ -236,8 +236,14 @@ return builder.getRoot(); } - private static String genClassName(Template operation) { - return getSimpleName(operation.getTemplateType()) + "Gen"; + private static String genClassName(NodeData node) { + String nodeid = node.getNodeId(); + if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { + nodeid = nodeid.substring(0, nodeid.length() - 4); + } + String name = Utils.firstLetterUpperCase(nodeid); + name += "GenNode"; + return name; } private String generatedGenericMethodName(SpecializationData specialization) { @@ -299,7 +305,7 @@ valuesNeedsCast = new HashSet<>(); for (GuardData guard : targetSpecialization.getGuards()) { for (ActualParameter parameter : guard.getParameters()) { - NodeFieldData field = node.findField(parameter.getSpecification().getName()); + NodeChildData field = node.findChild(parameter.getSpecification().getName()); if (field == null) { continue; } @@ -366,8 +372,8 @@ CodeTreeBuilder builder = new CodeTreeBuilder(parent); // Implict guards based on method signature for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { - NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName()); - if (field == null || field.getKind() == FieldKind.FINAL_FIELD) { + NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName()); + if (field == null) { continue; } ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); @@ -391,8 +397,8 @@ // Implict guards based on method signature String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { - NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName()); - if (field == null || field.getKind() == FieldKind.FINAL_FIELD) { + NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName()); + if (field == null) { continue; } ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); @@ -410,7 +416,7 @@ return builder.isEmpty() ? null : builder.getRoot(); } - private CodeTree createImplicitGuard(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) { + private CodeTree createImplicitGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, ActualParameter target) { NodeData node = field.getNodeData(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); @@ -444,7 +450,7 @@ return builder.getRoot(); } - private CodeTree createCast(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) { + private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, ActualParameter target) { NodeData node = field.getNodeData(); TypeData sourceType = source.getTypeSystemType(); TypeData targetType = target.getTypeSystemType(); @@ -503,22 +509,49 @@ builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end(); } + private static List findUserConstructors(TypeMirror nodeType) { + List constructors = new ArrayList<>(); + for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(nodeType).getEnclosedElements())) { + if (constructor.getModifiers().contains(PRIVATE)) { + continue; + } + if (isCopyConstructor(constructor)) { + continue; + } + constructors.add(constructor); + } + + if (constructors.isEmpty()) { + constructors.add(new CodeExecutableElement(null, Utils.getSimpleName(nodeType))); + } + + return constructors; + } + + private static boolean isCopyConstructor(ExecutableElement element) { + if (element.getParameters().size() != 1) { + return false; + } + VariableElement var = element.getParameters().get(0); + TypeElement type = Utils.findNearestEnclosingType(var); + + if (!Utils.typeEquals(var.asType(), type.asType())) { + return false; + } + return true; + } + @Override protected void createChildren(NodeData node) { Map> childTypes = new LinkedHashMap<>(); - if (node.getDeclaredChildren() != null && !node.getDeclaredChildren().isEmpty()) { - for (NodeData nodeChild : node.getDeclaredChildren()) { + if (node.getDeclaredNodes() != null && !node.getDeclaredNodes().isEmpty()) { + for (NodeData nodeChild : node.getDeclaredNodes()) { NodeCodeGenerator generator = new NodeCodeGenerator(getContext()); childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements()); } } - if (node.getExtensionElements() != null && !node.getExtensionElements().isEmpty()) { - NodeGenFactory factory = new NodeGenFactory(context); - add(factory, node); - } - - if (node.needsFactory() || node.getNodeChildren().size() > 0) { + if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) { add(new NodeFactoryFactory(context, childTypes), node); } } @@ -531,36 +564,130 @@ @Override protected CodeTypeElement create(NodeData node) { - CodeTypeElement clazz = createClass(node, modifiers(PUBLIC, ABSTRACT), genClassName(node), node.getTemplateType().asType(), false); - - for (ExecutableElement executable : ElementFilter.constructorsIn(node.getTemplateType().getEnclosedElements())) { - CodeExecutableElement superConstructor = createSuperConstructor(clazz, executable); + CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), genClassName(node), node.getNodeType(), false); - if (superConstructor != null) { - if (superConstructor.getParameters().size() == 1 && Utils.typeEquals(superConstructor.getParameters().get(0).asType(), node.getTemplateType().asType())) { - String originalName = superConstructor.getParameters().get(0).getSimpleName().toString(); - superConstructor.getParameters().clear(); - superConstructor.getParameters().add(new CodeVariableElement(clazz.asType(), originalName)); - } - clazz.add(superConstructor); - } + for (NodeChildData child : node.getChildren()) { + clazz.add(createChildField(child)); } + createConstructors(node, clazz); + if (node.getExtensionElements() != null) { clazz.getEnclosedElements().addAll(node.getExtensionElements()); } - node.setNodeType(clazz.asType()); - return clazz; } + private void createConstructors(NodeData node, CodeTypeElement clazz) { + List signatureConstructors = new ArrayList<>(); + ExecutableElement copyConstructor = null; + List constructors = ElementFilter.constructorsIn(Utils.fromTypeMirror(node.getNodeType()).getEnclosedElements()); + for (ExecutableElement constructor : constructors) { + if (constructor.getModifiers().contains(Modifier.PRIVATE) || constructor.getParameters().isEmpty()) { + continue; + } + + if (isCopyConstructor(constructor)) { + assert copyConstructor == null; + copyConstructor = createConstructor(clazz, constructor, true); + } else { + signatureConstructors.add(createConstructor(clazz, constructor, false)); + } + } + + if (copyConstructor == null && node.needsRewrites(getContext())) { + clazz.add(createConstructor(clazz, null, true)); + } else if (copyConstructor != null) { + clazz.add(copyConstructor); + } + + if (signatureConstructors.isEmpty() && !node.getChildren().isEmpty()) { + clazz.add(createConstructor(clazz, null, false)); + } else { + clazz.getEnclosedElements().addAll(signatureConstructors); + } + } + + private CodeExecutableElement createConstructor(CodeTypeElement type, ExecutableElement superConstructor, boolean copyConstructor) { + CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); + CodeTreeBuilder builder = method.createBuilder(); + if (!copyConstructor) { + if (superConstructor != null) { + for (VariableElement param : superConstructor.getParameters()) { + method.getParameters().add(CodeVariableElement.clone(param)); + } + } + for (NodeChildData child : getModel().getChildren()) { + method.getParameters().add(new CodeVariableElement(child.getNodeType(), child.getName())); + } + } else { + if (!(superConstructor == null && getModel().getChildren().isEmpty())) { + method.getParameters().add(new CodeVariableElement(type.asType(), "copy")); + } + } + + if (superConstructor != null) { + builder.startStatement(); + builder.startSuperCall(); + if (copyConstructor) { + builder.string("copy"); + } else { + for (VariableElement param : superConstructor.getParameters()) { + builder.string(param.getSimpleName().toString()); + } + } + builder.end(); + builder.end(); + } + + for (NodeChildData child : getModel().getChildren()) { + + builder.startStatement(); + builder.string("this.").string(child.getName()).string(" = "); + + if (child.getCardinality() == Cardinality.MANY) { + builder.startCall("adoptChildren"); + } else { + builder.startCall("adoptChild"); + } + + builder.startGroup(); + if (copyConstructor) { + builder.string("copy."); + } + builder.string(child.getName()); + builder.end(); + + builder.end(); + builder.end(); + + } + + return method; + } + + private CodeVariableElement createChildField(NodeChildData child) { + DeclaredType annotationType; + if (child.getCardinality() == Cardinality.MANY) { + annotationType = getContext().getTruffleTypes().getChildrenAnnotation(); + } else { + annotationType = getContext().getTruffleTypes().getChildAnnotation(); + } + + CodeVariableElement var = new CodeVariableElement(child.getNodeType(), child.getName()); + var.getModifiers().add(Modifier.PROTECTED); + var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType)); + return var; + } } private class NodeFactoryFactory extends ClassElementFactory { private final Map> childTypes; + private CodeTypeElement generatedNode; + public NodeFactoryFactory(ProcessorContext context, Map> childElements) { super(context); this.childTypes = childElements; @@ -585,6 +712,10 @@ Modifier createVisibility = Utils.getVisibility(clazz.getModifiers()); if (node.needsFactory()) { + NodeGenFactory factory = new NodeGenFactory(context); + add(factory, node); + generatedNode = factory.getElement(); + createFactoryMethods(node, clazz, createVisibility); if (node.getSpecializations().size() > 1) { @@ -603,15 +734,15 @@ } for (SpecializationData specialization : node.getSpecializations()) { - add(new SpecializedNodeFactory(context), specialization); + add(new SpecializedNodeFactory(context, generatedNode), specialization); } - TypeMirror nodeFactory = getContext().getEnvironment().getTypeUtils().getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType()); + TypeMirror nodeFactory = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType()); clazz.getImplements().add(nodeFactory); clazz.add(createCreateNodeMethod(node)); clazz.add(createCreateNodeSpecializedMethod(node)); clazz.add(createGetNodeClassMethod(node)); - clazz.add(createGetNodeSignaturesMethod(node)); + clazz.add(createGetNodeSignaturesMethod()); clazz.add(createGetChildrenSignatureMethod(node)); clazz.add(createGetInstanceMethod(node, createVisibility)); clazz.add(createInstanceConstant(node, clazz.asType())); @@ -636,7 +767,7 @@ } } - List children = node.getNodeChildren(); + List children = node.getNodeDeclaringChildren(); if (node.getParent() == null && children.size() > 0) { clazz.add(createGetFactories(node)); } @@ -644,24 +775,22 @@ } private CodeExecutableElement createGetNodeClassMethod(NodeData node) { - Types types = getContext().getEnvironment().getTypeUtils(); - TypeMirror returnType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType()); + TypeMirror returnType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType()); CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass"); CodeTreeBuilder builder = method.createBuilder(); builder.startReturn().typeLiteral(node.getNodeType()).end(); return method; } - private CodeExecutableElement createGetNodeSignaturesMethod(NodeData node) { - Types types = getContext().getEnvironment().getTypeUtils(); + private CodeExecutableElement createGetNodeSignaturesMethod() { TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class)); TypeMirror classType = getContext().getType(Class.class); - TypeMirror returnType = types.getDeclaredType(listType, types.getDeclaredType(listType, classType)); + TypeMirror returnType = Utils.getDeclaredType(listType, Utils.getDeclaredType(listType, classType)); CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeSignatures"); CodeTreeBuilder builder = method.createBuilder(); builder.startReturn(); builder.startStaticCall(getContext().getType(Arrays.class), "asList"); - List constructors = findUserConstructors(node); + List constructors = findUserConstructors(generatedNode.asType()); for (ExecutableElement constructor : constructors) { builder.tree(createAsList(builder, Utils.asTypeMirrors(constructor.getParameters()), classType)); } @@ -676,8 +805,8 @@ TypeMirror classType = getContext().getType(Class.class); TypeMirror nodeType = getContext().getTruffleTypes().getNode(); TypeMirror wildcardNodeType = types.getWildcardType(nodeType, null); - classType = types.getDeclaredType(Utils.fromTypeMirror(classType), wildcardNodeType); - TypeMirror returnType = types.getDeclaredType(listType, classType); + classType = Utils.getDeclaredType(Utils.fromTypeMirror(classType), wildcardNodeType); + TypeMirror returnType = Utils.getDeclaredType(listType, classType); CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getExecutionSignature"); CodeTreeBuilder builder = method.createBuilder(); @@ -687,16 +816,16 @@ SpecializationData data = node.getSpecializations().get(0); for (ActualParameter parameter : data.getParameters()) { ParameterSpec spec = parameter.getSpecification(); - NodeFieldData field = node.findField(spec.getName()); - if (field == null || field.getKind() == FieldKind.FINAL_FIELD) { + NodeChildData field = node.findChild(spec.getName()); + if (field == null) { continue; } TypeMirror type; - if (field.getKind() == FieldKind.CHILDREN && field.getType().getKind() == TypeKind.ARRAY) { - type = ((ArrayType) field.getType()).getComponentType(); + if (field.getCardinality() == Cardinality.MANY && field.getNodeType().getKind() == TypeKind.ARRAY) { + type = ((ArrayType) field.getNodeType()).getComponentType(); } else { - type = field.getType(); + type = field.getNodeType(); } signatureTypes.add(type); @@ -726,7 +855,7 @@ method.addParameter(arguments); CodeTreeBuilder builder = method.createBuilder(); - List signatures = findUserConstructors(node); + List signatures = findUserConstructors(generatedNode.asType()); boolean ifStarted = false; for (ExecutableElement element : signatures) { @@ -805,9 +934,8 @@ } private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) { - Types types = getContext().getEnvironment().getTypeUtils(); TypeElement nodeFactoryType = Utils.fromTypeMirror(getContext().getType(NodeFactory.class)); - TypeMirror returnType = types.getDeclaredType(nodeFactoryType, node.getNodeType()); + TypeMirror returnType = Utils.getDeclaredType(nodeFactoryType, node.getNodeType()); CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance"); if (visibility != null) { @@ -850,7 +978,7 @@ } private ExecutableElement createGetFactories(NodeData node) { - List children = node.getNodeChildren(); + List children = node.getNodeDeclaringChildren(); if (node.needsFactory()) { children.add(node); } @@ -871,11 +999,11 @@ TypeMirror factoryType = getContext().getType(NodeFactory.class); TypeMirror baseType; if (allSame) { - baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType); + baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType); } else { - baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null)); + baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null)); } - TypeMirror listType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType); + TypeMirror listType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType); CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories"); @@ -904,28 +1032,12 @@ } private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) { - List constructors = findUserConstructors(node); + List constructors = findUserConstructors(generatedNode.asType()); for (ExecutableElement constructor : constructors) { clazz.add(createCreateMethod(node, createVisibility, constructor)); } } - private List findUserConstructors(NodeData node) { - List constructors = new ArrayList<>(); - for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(node.getNodeType()).getEnclosedElements())) { - if (constructor.getModifiers().contains(PRIVATE)) { - continue; - } - - // skip node rewrite constructor - if (constructor.getParameters().size() == 1 && typeEquals(constructor.getParameters().get(0).asType(), node.getNodeType())) { - continue; - } - constructors.add(constructor); - } - return constructors; - } - private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) { CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), constructor); method.setSimpleName(CodeNames.of("create")); @@ -962,6 +1074,12 @@ method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "specializationClass")); CodeTreeBuilder body = method.createBuilder(); + + body.startStatement(); + body.type(generatedNode.asType()).string(" ").string(THIS_NODE_LOCAL_VAR_NAME + "Cast"); + body.string(" = ").string("(").type(generatedNode.asType()).string(") ").string(THIS_NODE_LOCAL_VAR_NAME); + body.end(); + boolean first = true; for (TypeData type : node.getTypeSystem().getTypes()) { SpecializationData specialization = node.findUniqueSpecialization(type); @@ -974,21 +1092,21 @@ } body.string("specializationClass == ").type(type.getBoxedType()).string(".class").end().startBlock(); body.startReturn().startNew(nodeSpecializationClassName(specialization)); - body.string(THIS_NODE_LOCAL_VAR_NAME); + body.string(THIS_NODE_LOCAL_VAR_NAME + "Cast"); body.end().end(); // new, return body.end(); // if } } body.startReturn().startNew(nodeSpecializationClassName(node.getGenericSpecialization())); - body.string(THIS_NODE_LOCAL_VAR_NAME); + body.string(THIS_NODE_LOCAL_VAR_NAME + "Cast"); body.end().end(); return method; } private CodeExecutableElement createSpecializeMethod(NodeData node) { CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), node.getNodeType(), "specialize"); - method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); + method.addParameter(new CodeVariableElement(generatedNode.asType(), THIS_NODE_LOCAL_VAR_NAME)); method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); addInternalValueParameters(method, node.getGenericSpecialization(), true); @@ -1100,14 +1218,21 @@ private class SpecializedNodeFactory extends ClassElementFactory { - public SpecializedNodeFactory(ProcessorContext context) { + private final CodeTypeElement nodeGen; + + public SpecializedNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) { super(context); + this.nodeGen = nodeGen; } @Override public CodeTypeElement create(SpecializationData specialization) { NodeData node = specialization.getNode(); - CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), node.getNodeType(), false); + TypeMirror baseType = node.getNodeType(); + if (nodeGen != null) { + baseType = nodeGen.asType(); + } + CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false); return clazz; } @@ -1231,8 +1356,8 @@ List executeParameters = new ArrayList<>(); for (ActualParameter sourceParameter : executable.getParameters()) { - NodeFieldData field = specialization.getNode().findField(sourceParameter.getSpecification().getName()); - if (field == null || field.getKind() == FieldKind.FINAL_FIELD) { + NodeChildData field = specialization.getNode().findChild(sourceParameter.getSpecification().getName()); + if (field == null) { continue; } @@ -1433,8 +1558,8 @@ CodeTreeBuilder builder = new CodeTreeBuilder(parent); for (ActualParameter targetParameter : targetParameters) { - NodeFieldData field = sourceNode.findField(targetParameter.getSpecification().getName()); - if (field == null || field.getKind() == FieldKind.FINAL_FIELD) { + NodeChildData field = sourceNode.findChild(targetParameter.getSpecification().getName()); + if (field == null) { continue; } TypeData targetType = targetParameter.getTypeSystemType(); @@ -1518,14 +1643,16 @@ return builder.getRoot(); } - private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeFieldData targetField, ActualParameter sourceParameter) { + private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetField, ActualParameter sourceParameter) { TypeData type = sourceParameter.getTypeSystemType(); ExecutableTypeData execType = targetField.getNodeData().findExecutableType(type); CodeTreeBuilder builder = new CodeTreeBuilder(parent); if (targetField != null) { Element accessElement = targetField.getAccessElement(); - if (accessElement.getKind() == ElementKind.METHOD) { + if (accessElement == null) { + builder.string("this.").string(targetField.getName()); + } else if (accessElement.getKind() == ElementKind.METHOD) { builder.startCall(accessElement.getSimpleName().toString()).end(); } else if (accessElement.getKind() == ElementKind.FIELD) { builder.string("this.").string(accessElement.getSimpleName().toString()); @@ -1549,7 +1676,7 @@ ActualParameter parameter, ActualParameter exceptionParam) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); - NodeFieldData forField = specialization.getNode().findField(parameter.getSpecification().getName()); + NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName()); if (forField == null) { return body; } @@ -1571,11 +1698,11 @@ return builder.getRoot(); } - private CodeTree createShortCircuitValue(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, NodeFieldData forField, + private CodeTree createShortCircuitValue(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, NodeChildData forField, ActualParameter shortCircuitParam, ActualParameter exceptionParam) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); int shortCircuitIndex = 0; - for (NodeFieldData field : specialization.getNode().getFields()) { + for (NodeChildData field : specialization.getNode().getChildren()) { if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) { if (field == forField) { break; diff -r 1964871a642d -r 97ad6d3e7557 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 Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Sat Apr 20 12:16:22 2013 +0200 @@ -28,8 +28,7 @@ import javax.lang.model.type.*; import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind; -import com.oracle.truffle.codegen.processor.node.NodeFieldData.FieldKind; +import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; import com.oracle.truffle.codegen.processor.template.*; import com.oracle.truffle.codegen.processor.typesystem.*; @@ -37,9 +36,11 @@ private final String nodeId; private NodeData declaringNode; - private List declaredChildren = new ArrayList<>(); + private List declaredNodes = new ArrayList<>(); + private boolean splitByMethodName; private TypeSystemData typeSystem; + private List children; private List fields; private TypeMirror nodeType; private ParameterSpec instanceParameterSpec; @@ -58,7 +59,7 @@ super(splitSource.getTemplateType(), templateMethodName, null); this.nodeId = nodeId; this.declaringNode = splitSource.declaringNode; - this.declaredChildren = splitSource.declaredChildren; + this.declaredNodes = splitSource.declaredNodes; this.typeSystem = splitSource.typeSystem; this.nodeType = splitSource.nodeType; this.specializations = splitSource.specializations; @@ -66,41 +67,58 @@ this.executableTypes = splitSource.executableTypes; this.shortCircuits = splitSource.shortCircuits; this.fields = splitSource.fields; + this.children = splitSource.children; + } + + public boolean isSplitByMethodName() { + return splitByMethodName; } void setTypeSystem(TypeSystemData typeSystem) { this.typeSystem = typeSystem; } + void setFields(List fields) { + this.fields = fields; + } + + public List getFields() { + return fields; + } + + void setSplitByMethodName(boolean splitByMethodName) { + this.splitByMethodName = splitByMethodName; + } + @Override protected List findChildContainers() { - List children = new ArrayList<>(); - if (declaredChildren != null) { - children.addAll(declaredChildren); + List containerChildren = new ArrayList<>(); + if (declaredNodes != null) { + containerChildren.addAll(declaredNodes); } if (typeSystem != null) { - children.add(typeSystem); + containerChildren.add(typeSystem); } if (specializations != null) { for (MessageContainer specialization : specializations) { if (specialization.getMessageElement() != null) { - children.add(specialization); + containerChildren.add(specialization); } } } if (specializationListeners != null) { - children.addAll(specializationListeners); + containerChildren.addAll(specializationListeners); } if (executableTypes != null) { - children.addAll(getExecutableTypes()); + containerChildren.addAll(getExecutableTypes()); } if (shortCircuits != null) { - children.addAll(shortCircuits); + containerChildren.addAll(shortCircuits); } - if (fields != null) { - children.addAll(fields); + if (containerChildren != null) { + containerChildren.addAll(containerChildren); } - return children; + return containerChildren; } public ParameterSpec getInstanceParameterSpec() { @@ -144,19 +162,19 @@ return true; } - public List getNodeChildren() { - List children = new ArrayList<>(); - for (NodeData child : getDeclaredChildren()) { + public List getNodeDeclaringChildren() { + List nodeChildren = new ArrayList<>(); + for (NodeData child : getDeclaredNodes()) { if (child.needsFactory()) { - children.add(child); + nodeChildren.add(child); } - children.addAll(child.getNodeChildren()); + nodeChildren.addAll(child.getNodeDeclaringChildren()); } - return children; + return nodeChildren; } - void setDeclaredChildren(List declaredChildren) { - this.declaredChildren = declaredChildren; + void setDeclaredNodes(List declaredChildren) { + this.declaredNodes = declaredChildren; for (NodeData child : declaredChildren) { child.declaringNode = this; @@ -167,8 +185,8 @@ return declaringNode; } - public List getDeclaredChildren() { - return declaredChildren; + public List getDeclaredNodes() { + return declaredNodes; } public void setNodeType(TypeMirror nodeType) { @@ -260,16 +278,14 @@ return result; } - public NodeFieldData[] filterFields(FieldKind fieldKind, ExecutionKind usage) { - List filteredFields = new ArrayList<>(); - for (NodeFieldData field : getFields()) { + public NodeChildData[] filterFields(ExecutionKind usage) { + List filteredFields = new ArrayList<>(); + for (NodeChildData field : getChildren()) { if (usage == null || field.getExecutionKind() == usage) { - if (fieldKind == null || field.getKind() == fieldKind) { - filteredFields.add(field); - } + filteredFields.add(field); } } - return filteredFields.toArray(new NodeFieldData[filteredFields.size()]); + return filteredFields.toArray(new NodeChildData[filteredFields.size()]); } public boolean needsRewrites(ProcessorContext context) { @@ -313,13 +329,13 @@ dumpProperty(builder, indent, "templateClass", Utils.getQualifiedName(getTemplateType())); dumpProperty(builder, indent, "typeSystem", getTypeSystem()); - dumpProperty(builder, indent, "fields", getFields()); + dumpProperty(builder, indent, "fields", getChildren()); dumpProperty(builder, indent, "executableTypes", getExecutableTypes()); dumpProperty(builder, indent, "specializations", getSpecializations()); dumpProperty(builder, indent, "messages", collectMessages()); - if (getDeclaredChildren().size() > 0) { + if (getDeclaredNodes().size() > 0) { builder.append(String.format("\n%s children = [", indent)); - for (NodeData node : getDeclaredChildren()) { + for (NodeData node : getDeclaredNodes()) { builder.append("\n"); builder.append(node.dump(level + 1)); } @@ -365,8 +381,8 @@ return b.toString(); } - public NodeFieldData findField(String name) { - for (NodeFieldData field : getFields()) { + public NodeChildData findChild(String name) { + for (NodeChildData field : getChildren()) { if (field.getName().equals(name)) { return field; } @@ -374,12 +390,12 @@ return null; } - public List getFields() { - return fields; + public List getChildren() { + return children; } - void setFields(List fields) { - this.fields = fields; + void setChildren(List fields) { + this.children = fields; } public List getSpecializations() { diff -r 1964871a642d -r 97ad6d3e7557 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 Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java Sat Apr 20 12:16:22 2013 +0200 @@ -29,88 +29,27 @@ public class NodeFieldData extends MessageContainer { - public enum FieldKind { - CHILD, CHILDREN, FINAL_FIELD - } - - public enum ExecutionKind { - DEFAULT, IGNORE, SHORT_CIRCUIT - } - - private final VariableElement fieldElement; - private final Element accessElement; - private final AnnotationMirror childAnnotationMirror; - - private final FieldKind fieldKind; - private final ExecutionKind executionKind; - private NodeData nodeData; + private VariableElement variable; - public NodeFieldData(VariableElement fieldElement, Element accessElement, AnnotationMirror childAnnotationMirror, FieldKind fieldKind, ExecutionKind executionKind) { - this.fieldElement = fieldElement; - this.accessElement = accessElement; - this.childAnnotationMirror = childAnnotationMirror; - this.fieldKind = fieldKind; - this.executionKind = executionKind; - } - - NodeFieldData(NodeFieldData field) { - this.fieldElement = field.fieldElement; - this.accessElement = field.accessElement; - this.childAnnotationMirror = field.childAnnotationMirror; - this.fieldKind = field.fieldKind; - this.executionKind = field.executionKind; - this.nodeData = field.nodeData; + public NodeFieldData(VariableElement var) { + this.variable = var; } @Override public Element getMessageElement() { - return fieldElement; - } - - public boolean isShortCircuit() { - return executionKind == ExecutionKind.SHORT_CIRCUIT; + return variable; } - void setNode(NodeData nodeData) { - this.nodeData = nodeData; - getMessages().addAll(nodeData.collectMessages()); - } - - public VariableElement getFieldElement() { - return fieldElement; - } - - public Element getAccessElement() { - return accessElement; - } - - public AnnotationMirror getChildAnnotationMirror() { - return childAnnotationMirror; + public String getName() { + return variable.getSimpleName().toString(); } public TypeMirror getType() { - return fieldElement.asType(); - } - - public FieldKind getKind() { - return fieldKind; - } - - public ExecutionKind getExecutionKind() { - return executionKind; + return variable.asType(); } - public NodeData getNodeData() { - return nodeData; - } - - public String getName() { - return fieldElement.getSimpleName().toString(); - } - - @Override - public String toString() { - return "NodeFieldData[name=" + getName() + ", kind=" + fieldKind + ", execution=" + executionKind + ", node=" + getNodeData() + "]"; + public VariableElement getVariable() { + return variable; } } diff -r 1964871a642d -r 97ad6d3e7557 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java Sat Apr 20 12:16:22 2013 +0200 @@ -28,9 +28,9 @@ import javax.lang.model.type.*; import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeFieldData.*; +import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; +import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; import com.oracle.truffle.codegen.processor.template.*; -import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; public abstract class NodeMethodParser extends TemplateMethodParser { @@ -84,37 +84,36 @@ resolveAndAddImplicitThis(methodSpec, method); for (NodeFieldData field : getNode().getFields()) { - if (field.getKind() == FieldKind.FINAL_FIELD) { + if (!Utils.isFieldAccessible(method, field.getVariable())) { ParameterSpec spec = new ParameterSpec(field.getName(), field.getType()); spec.setLocal(true); methodSpec.addOptional(spec); } } - for (NodeFieldData field : getNode().getFields()) { - if (field.getExecutionKind() == ExecutionKind.IGNORE) { - continue; - } + // children are null when parsing executable types + if (getNode().getChildren() != null) { + for (NodeChildData child : getNode().getChildren()) { + if (child.getExecutionKind() == ExecutionKind.DEFAULT) { + ParameterSpec spec = createValueParameterSpec(child.getName(), child.getNodeData()); + if (child.getCardinality().isMany()) { + spec.setCardinality(Cardinality.MANY); + spec.setIndexed(true); + } + methodSpec.addRequired(spec); + } else if (child.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) { + String valueName = child.getName(); + if (shortCircuitName != null && valueName.equals(shortCircuitName)) { + break; + } - if (field.getExecutionKind() == ExecutionKind.DEFAULT) { - ParameterSpec spec = createValueParameterSpec(field.getName(), field.getNodeData()); - if (field.getKind() == FieldKind.CHILDREN) { - spec.setCardinality(Cardinality.MULTIPLE); - spec.setIndexed(true); + if (shortCircuitsEnabled) { + methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class))); + } + methodSpec.addRequired(createValueParameterSpec(valueName, child.getNodeData())); + } else { + assert false; } - methodSpec.addRequired(spec); - } else if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) { - String valueName = field.getName(); - if (shortCircuitName != null && valueName.equals(shortCircuitName)) { - break; - } - - if (shortCircuitsEnabled) { - methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class))); - } - methodSpec.addRequired(createValueParameterSpec(valueName, field.getNodeData())); - } else { - assert false; } } diff -r 1964871a642d -r 97ad6d3e7557 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 Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Sat Apr 20 12:16:22 2013 +0200 @@ -31,11 +31,10 @@ import javax.tools.Diagnostic.Kind; import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.api.nodes.Node.Child; -import com.oracle.truffle.api.nodes.Node.Children; +import com.oracle.truffle.api.codegen.NodeClass.InheritNode; import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind; -import com.oracle.truffle.codegen.processor.node.NodeFieldData.FieldKind; +import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; +import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; import com.oracle.truffle.codegen.processor.template.*; import com.oracle.truffle.codegen.processor.typesystem.*; @@ -74,7 +73,7 @@ @Override protected NodeData filterErrorElements(NodeData model) { - for (Iterator iterator = model.getDeclaredChildren().iterator(); iterator.hasNext();) { + for (Iterator iterator = model.getDeclaredNodes().iterator(); iterator.hasNext();) { NodeData node = filterErrorElements(iterator.next()); if (node == null) { iterator.remove(); @@ -115,73 +114,100 @@ parsedNodes.put(typeName, rootNode); if (rootNode != null) { - children.addAll(rootNode.getDeclaredChildren()); - rootNode.setDeclaredChildren(children); + children.addAll(rootNode.getDeclaredNodes()); + rootNode.setDeclaredNodes(children); } return rootNode; } - private NodeData parseNode(TypeElement type) { - if (Utils.findAnnotationMirror(processingEnv, type, GeneratedBy.class) != null) { + private NodeData parseNode(TypeElement templateType) { + if (Utils.findAnnotationMirror(processingEnv, templateType, GeneratedBy.class) != null) { // generated nodes should not get called again. return null; } - AnnotationMirror methodNodes = Utils.findAnnotationMirror(processingEnv, type, NodeClass.class); + AnnotationMirror methodNodes = Utils.findAnnotationMirror(processingEnv, templateType, NodeClass.class); - if (methodNodes == null && !Utils.isAssignable(type.asType(), context.getTruffleTypes().getNode())) { + if (methodNodes == null && !Utils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) { return null; // not a node } - if (type.getModifiers().contains(Modifier.PRIVATE)) { + if (templateType.getModifiers().contains(Modifier.PRIVATE)) { // TODO error message here!? return null; // not visible, not a node } - TypeElement nodeType; - boolean needsSplit; - if (methodNodes != null) { - needsSplit = methodNodes != null; - nodeType = Utils.fromTypeMirror(Utils.getAnnotationValue(TypeMirror.class, methodNodes, "value")); - } else { - needsSplit = false; - nodeType = type; + List lookupTypes = findSuperClasses(new ArrayList(), templateType); + Collections.reverse(lookupTypes); + + AnnotationMirror nodeClass = findFirstAnnotation(lookupTypes, NodeClass.class); + TypeMirror nodeType = null; + if (Utils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) { + nodeType = templateType.asType(); + } + if (nodeClass != null) { + nodeType = inheritType(nodeClass, "value", nodeType); + } + + if (nodeType == null) { + // FIXME error + return null; } - NodeData nodeData = parseNodeData(type, nodeType); + Set elementSet = new HashSet<>(context.getEnvironment().getElementUtils().getAllMembers(templateType)); + if (!Utils.typeEquals(templateType.asType(), nodeType)) { + elementSet.addAll(context.getEnvironment().getElementUtils().getAllMembers(Utils.fromTypeMirror(nodeType))); + + List nodeLookupTypes = findSuperClasses(new ArrayList(), Utils.fromTypeMirror(nodeType)); + Collections.reverse(nodeLookupTypes); + lookupTypes.addAll(nodeLookupTypes); - if (nodeData.hasErrors()) { - return nodeData; // error sync point + Set types = new HashSet<>(); + for (ListIterator iterator = lookupTypes.listIterator(); iterator.hasNext();) { + TypeElement typeElement = iterator.next(); + if (types.contains(typeElement)) { + iterator.remove(); + } else { + types.add(typeElement); + } + } + } + List elements = new ArrayList<>(elementSet); + + NodeData node = parseNodeData(templateType, nodeType, elements, lookupTypes); + + if (node.hasErrors()) { + return node; // error sync point } - List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(type)); - parseMethods(nodeData, elements); + parseMethods(node, elements); - if (nodeData.hasErrors()) { - return nodeData; + if (node.hasErrors()) { + return node; } List nodes; - if (needsSplit) { - nodes = splitNodeData(nodeData); + + if (node.isSplitByMethodName()) { + nodes = splitNodeData(node); } else { nodes = new ArrayList<>(); - nodes.add(nodeData); + nodes.add(node); } for (NodeData splittedNode : nodes) { finalizeSpecializations(elements, splittedNode); - verifyNode(splittedNode); + verifyNode(splittedNode, elements); } - if (needsSplit) { - nodeData.setDeclaredChildren(nodes); - nodeData.setSpecializationListeners(new ArrayList()); - nodeData.setSpecializations(new ArrayList()); - return nodeData; + if (node.isSplitByMethodName()) { + node.setDeclaredNodes(nodes); + node.setSpecializationListeners(new ArrayList()); + node.setSpecializations(new ArrayList()); + return node; } else { - return nodeData; + return node; } } @@ -295,12 +321,12 @@ List parameters = new ArrayList<>(); for (ActualParameter specializationParameter : specialization.getParameters()) { ParameterSpec parameterSpec = specification.findParameterSpec(specializationParameter.getSpecification().getName()); - NodeFieldData field = node.findField(parameterSpec.getName()); + NodeChildData child = node.findChild(parameterSpec.getName()); TypeData actualType; - if (field == null || field.getKind() == FieldKind.FINAL_FIELD) { + if (child == null) { actualType = specializationParameter.getTypeSystemType(); } else { - ExecutableTypeData paramType = field.getNodeData().findAnyGenericExecutableType(context); + ExecutableTypeData paramType = child.getNodeData().findAnyGenericExecutableType(context); assert paramType != null; actualType = paramType.getType(); } @@ -396,7 +422,7 @@ List paramIds = new LinkedList<>(); paramIds.add(Utils.getTypeId(other.getReturnType().getType())); for (ActualParameter param : other.getParameters()) { - if (other.getNode().findField(param.getSpecification().getName()) == null) { + if (other.getNode().findChild(param.getSpecification().getName()) == null) { continue; } paramIds.add(Utils.getTypeId(param.getType())); @@ -498,11 +524,11 @@ return signatures; } - private void verifyNode(NodeData nodeData) { + private void verifyNode(NodeData nodeData, List elements) { // verify order is not ambiguous verifySpecializationOrder(nodeData); - verifyMissingAbstractMethods(nodeData); + verifyMissingAbstractMethods(nodeData, elements); assignShortCircuitsToSpecializations(nodeData); @@ -513,15 +539,12 @@ 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); + private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List elements, List lookupTypes) { NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString()); - AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); + AnnotationMirror typeSystemMirror = findFirstAnnotation(lookupTypes, TypeSystemReference.class); if (typeSystemMirror == null) { - nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), nodeType.getQualifiedName().toString()); + nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(nodeType)); return nodeData; } @@ -532,23 +555,21 @@ return nodeData; } - nodeData.setNodeType(nodeType.asType()); - nodeData.setTypeSystem(typeSystem); - nodeData.setFields(parseFields(elements, typeHierarchy)); - - if (Utils.typeEquals(nodeType.asType(), templateType.asType())) { - // filter fields if they were not split. (field are accessible anyway) - for (ListIterator iterator = nodeData.getFields().listIterator(); iterator.hasNext();) { - NodeFieldData field = iterator.next(); - if (field.getKind() == FieldKind.FINAL_FIELD) { - iterator.remove(); - } - } + boolean splitByMethodName = false; + AnnotationMirror nodeClass = findFirstAnnotation(lookupTypes, NodeClass.class); + if (nodeClass != null) { + splitByMethodName = Utils.getAnnotationValue(Boolean.class, nodeClass, "splitByMethodName"); } + nodeData.setNodeType(nodeType); + nodeData.setSplitByMethodName(splitByMethodName); + nodeData.setTypeSystem(typeSystem); + nodeData.setFields(parseFields(elements)); nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements))); + parsedNodes.put(Utils.getQualifiedName(templateType), nodeData); - parsedNodes.put(Utils.getQualifiedName(templateType), nodeData); + // parseChildren invokes cyclic parsing. + nodeData.setChildren(parseChildren(elements, lookupTypes)); return nodeData; } @@ -577,14 +598,14 @@ return valid; } - private void verifyMissingAbstractMethods(NodeData nodeData) { + private static void verifyMissingAbstractMethods(NodeData nodeData, List originalElements) { if (!nodeData.needsFactory()) { // missing abstract methods only needs to be implemented // if we need go generate factory for it. return; } - List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(nodeData.getTemplateType())); + List elements = new ArrayList<>(originalElements); Set unusedElements = new HashSet<>(elements); for (TemplateMethod method : nodeData.getAllTemplateMethods()) { @@ -594,6 +615,12 @@ unusedElements.removeAll(nodeData.getExtensionElements()); } + for (NodeChildData child : nodeData.getChildren()) { + if (child.getAccessElement() != null) { + unusedElements.remove(child.getAccessElement()); + } + } + for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) { if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) { nodeData.addError("The type %s must implement the inherited abstract method %s.", Utils.getSimpleName(nodeData.getTemplateType()), Utils.getReadableSignature(unusedMethod)); @@ -608,8 +635,17 @@ } TypeElement type = Utils.fromTypeMirror(nodeData.getNodeType()); + List constructors = ElementFilter.constructorsIn(type.getEnclosedElements()); - List constructors = ElementFilter.constructorsIn(type.getEnclosedElements()); + boolean parametersFound = false; + for (ExecutableElement constructor : constructors) { + if (!constructor.getParameters().isEmpty()) { + parametersFound = true; + } + } + if (!parametersFound) { + return; + } for (ExecutableElement e : constructors) { if (e.getParameters().size() == 1) { TypeMirror firstArg = e.getParameters().get(0).asType(); @@ -657,16 +693,20 @@ return null; } - private List parseFields(List elements, final List typeHierarchy) { - AnnotationMirror executionOrderMirror = findFirstAnnotation(typeHierarchy, ExecuteChildren.class); - List executionDefinition = null; - if (executionOrderMirror != null) { - executionDefinition = new ArrayList<>(); - for (String object : Utils.getAnnotationValueList(String.class, executionOrderMirror, "value")) { - executionDefinition.add(object); + private static List parseFields(List elements) { + List fields = new ArrayList<>(); + for (VariableElement field : ElementFilter.fieldsIn(elements)) { + if (field.getModifiers().contains(Modifier.STATIC)) { + continue; + } + if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) { + fields.add(new NodeFieldData(field)); } } + return fields; + } + private List parseChildren(List elements, final List typeHierarchy) { Set shortCircuits = new HashSet<>(); for (ExecutableElement method : ElementFilter.methodsIn(elements)) { AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class); @@ -675,136 +715,114 @@ } } - List fields = new ArrayList<>(); - for (VariableElement var : ElementFilter.fieldsIn(elements)) { - if (var.getModifiers().contains(Modifier.STATIC)) { - continue; + List parsedChildren = new ArrayList<>(); + List typeHierarchyReversed = new ArrayList<>(typeHierarchy); + Collections.reverse(typeHierarchyReversed); + for (TypeElement type : typeHierarchyReversed) { + AnnotationMirror nodeClassMirror = Utils.findAnnotationMirror(processingEnv, type, NodeClass.class); + AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, type, NodeChildren.class); + + TypeMirror nodeClassType = type.getSuperclass(); + if (!Utils.isAssignable(nodeClassType, context.getTruffleTypes().getNode())) { + nodeClassType = null; } - if (executionDefinition != null) { - if (!executionDefinition.contains(var.getSimpleName().toString())) { - continue; - } + if (nodeClassMirror != null) { + nodeClassType = inheritType(nodeClassMirror, "value", nodeClassType); } - NodeFieldData field = parseField(var, shortCircuits); - if (field != null) { - fields.add(field); - } - } - sortByExecutionOrder(fields, executionDefinition == null ? Collections. emptyList() : executionDefinition, typeHierarchy); - return fields; - } + List children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class); + for (AnnotationMirror childMirror : children) { + String name = Utils.getAnnotationValue(String.class, childMirror, "value"); + + Cardinality cardinality = Cardinality.ONE; - private NodeFieldData parseField(VariableElement var, Set foundShortCircuits) { - AnnotationMirror childMirror = Utils.findAnnotationMirror(processingEnv, var, Child.class); - AnnotationMirror childrenMirror = Utils.findAnnotationMirror(processingEnv, var, Children.class); - - FieldKind kind; + TypeMirror childType = inheritType(childMirror, "type", nodeClassType); + if (childType.getKind() == TypeKind.ARRAY) { + cardinality = Cardinality.MANY; + } - ExecutionKind execution; - if (foundShortCircuits.contains(var.getSimpleName().toString())) { - execution = ExecutionKind.SHORT_CIRCUIT; - } else { - execution = ExecutionKind.DEFAULT; - } + Element getter = findGetter(elements, name, childType); - AnnotationMirror mirror; - TypeMirror type; + ExecutionKind kind = ExecutionKind.DEFAULT; + if (shortCircuits.contains(name)) { + kind = ExecutionKind.SHORT_CIRCUIT; + } - if (childMirror != null) { - mirror = childMirror; - type = var.asType(); - kind = FieldKind.CHILD; - } else if (childrenMirror != null) { - mirror = childrenMirror; - type = getComponentType(var.asType()); - kind = FieldKind.CHILDREN; - } else { - execution = ExecutionKind.IGNORE; - type = var.asType(); - mirror = null; - kind = FieldKind.FINAL_FIELD; - } + NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, getter, cardinality, kind); + + parsedChildren.add(nodeChild); + + verifyNodeChild(nodeChild); + if (nodeChild.hasErrors()) { + continue; + } - NodeFieldData fieldData = new NodeFieldData(var, findAccessElement(var), mirror, kind, execution); - if (type != null && mirror != null) { - TypeElement typeElement = Utils.fromTypeMirror(type); - if (typeElement == null) { - return null; - } - NodeData fieldNodeData = resolveNode(typeElement); - fieldData.setNode(fieldNodeData); + NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(childType)); + nodeChild.setNode(fieldNodeData); - if (fieldNodeData == null) { - fieldData.addError("Node type '%s' is invalid.", Utils.getQualifiedName(type)); - } else if (fieldNodeData.findGenericExecutableTypes(context).isEmpty()) { - fieldData.addError("No executable generic types found for node '%s'.", Utils.getQualifiedName(type)); + if (fieldNodeData == null) { + nodeChild.addError("Node type '%s' is invalid.", Utils.getQualifiedName(type)); + } else if (fieldNodeData.findGenericExecutableTypes(context).isEmpty()) { + nodeChild.addError("No executable generic types found for node '%s'.", Utils.getQualifiedName(type)); + } } } - if (fieldData.getAccessElement().getModifiers().contains(Modifier.PRIVATE)) { - return null; + List filteredChildren = new ArrayList<>(); + Set encounteredNames = new HashSet<>(); + for (int i = parsedChildren.size() - 1; i >= 0; i--) { + NodeChildData child = parsedChildren.get(i); + if (!encounteredNames.contains(child.getName())) { + filteredChildren.add(0, child); + encounteredNames.add(child.getName()); + } } - - return fieldData; + return filteredChildren; } - private Element findAccessElement(VariableElement variableElement) { - Element enclosed = variableElement.getEnclosingElement(); - if (!enclosed.getKind().isClass()) { - throw new IllegalArgumentException("Field must be enclosed in a class."); - } - - String methodName; - if (Utils.typeEquals(variableElement.asType(), context.getType(boolean.class))) { - methodName = "is" + Utils.firstLetterUpperCase(variableElement.getSimpleName().toString()); - } else { - methodName = "get" + Utils.firstLetterUpperCase(variableElement.getSimpleName().toString()); + private static void verifyNodeChild(NodeChildData nodeChild) { + if (nodeChild.getNodeType() == null) { + nodeChild.addError("No valid node type could be resoleved."); } + // FIXME verify node child + // FIXME verify node type set + } - ExecutableElement getter = null; - for (ExecutableElement method : ElementFilter.methodsIn(enclosed.getEnclosedElements())) { - if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && !Utils.typeEquals(method.getReturnType(), context.getType(void.class))) { - getter = method; - break; - } - } - if (getter != null && !getter.getModifiers().contains(Modifier.PRIVATE)) { - return getter; + private TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) { + TypeMirror inhertNodeType = context.getType(InheritNode.class); + TypeMirror value = Utils.getAnnotationValue(TypeMirror.class, annotation, valueName); + if (Utils.typeEquals(inhertNodeType, value)) { + return parentType; } else { - return variableElement; + return value; } } - private static void sortByExecutionOrder(List fields, final List executionOrder, final List typeHierarchy) { - Collections.sort(fields, new Comparator() { + private Element findGetter(List elements, String variableName, TypeMirror type) { + if (type == null) { + return null; + } + String methodName; + if (Utils.typeEquals(type, context.getType(boolean.class))) { + methodName = "is" + Utils.firstLetterUpperCase(variableName); + } else { + methodName = "get" + Utils.firstLetterUpperCase(variableName); + } - @Override - public int compare(NodeFieldData o1, NodeFieldData o2) { - // sort by execution order - int index1 = executionOrder.indexOf(o1.getName()); - int index2 = executionOrder.indexOf(o2.getName()); - if (index1 == -1 || index2 == -1) { - // sort by type hierarchy - index1 = typeHierarchy.indexOf(o1.getFieldElement().getEnclosingElement()); - index2 = typeHierarchy.indexOf(o2.getFieldElement().getEnclosingElement()); - - // finally sort by name (will emit warning) - if (index1 == -1 || index2 == -1) { - return o1.getName().compareTo(o2.getName()); - } - } - return index1 - index2; + for (ExecutableElement method : ElementFilter.methodsIn(elements)) { + if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.typeEquals(method.getReturnType(), type)) { + return method; } - }); + } + return null; } private void assignShortCircuitsToSpecializations(NodeData node) { Map> groupedShortCircuits = groupShortCircuits(node.getShortCircuits()); boolean valid = true; - for (NodeFieldData field : node.filterFields(null, ExecutionKind.SHORT_CIRCUIT)) { + for (NodeChildData field : node.filterFields(ExecutionKind.SHORT_CIRCUIT)) { String valueName = field.getName(); List availableCircuits = groupedShortCircuits.get(valueName); @@ -855,7 +873,7 @@ return; } - NodeFieldData[] fields = node.filterFields(null, ExecutionKind.SHORT_CIRCUIT); + NodeChildData[] fields = node.filterFields(ExecutionKind.SHORT_CIRCUIT); for (SpecializationData specialization : node.getSpecializations()) { List assignedShortCuts = new ArrayList<>(fields.length); @@ -892,8 +910,8 @@ private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) { for (ActualParameter parameter : method.getParameters()) { - NodeFieldData field = node.findField(parameter.getSpecification().getName()); - if (field == null || field.getKind() == FieldKind.FINAL_FIELD) { + NodeChildData field = node.findChild(parameter.getSpecification().getName()); + if (field == null) { continue; } ExecutableTypeData found = null; @@ -924,13 +942,6 @@ return group; } - private TypeMirror getComponentType(TypeMirror type) { - if (type instanceof ArrayType) { - return getComponentType(((ArrayType) type).getComponentType()); - } - return type; - } - private static List findSuperClasses(List collection, TypeElement element) { if (element.getSuperclass() != null) { TypeElement superElement = Utils.fromTypeMirror(element.getSuperclass()); diff -r 1964871a642d -r 97ad6d3e7557 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 Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitParser.java Sat Apr 20 12:16:22 2013 +0200 @@ -29,7 +29,7 @@ import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind; +import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; import com.oracle.truffle.codegen.processor.template.*; public class ShortCircuitParser extends NodeMethodParser { @@ -40,8 +40,8 @@ super(context, node); shortCircuitValues = new HashSet<>(); - NodeFieldData[] shortCircuitFields = node.filterFields(null, ExecutionKind.SHORT_CIRCUIT); - for (NodeFieldData field : shortCircuitFields) { + NodeChildData[] shortCircuitFields = node.filterFields(ExecutionKind.SHORT_CIRCUIT); + for (NodeChildData field : shortCircuitFields) { shortCircuitValues.add(field.getName()); } } diff -r 1964871a642d -r 97ad6d3e7557 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 Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Sat Apr 20 12:16:22 2013 +0200 @@ -26,7 +26,6 @@ import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeFieldData.*; import com.oracle.truffle.codegen.processor.template.*; import com.oracle.truffle.codegen.processor.typesystem.*; @@ -83,8 +82,8 @@ return true; } for (ActualParameter parameter : getParameters()) { - NodeFieldData field = getNode().findField(parameter.getSpecification().getName()); - if (field == null || field.getKind() == FieldKind.FINAL_FIELD) { + NodeChildData field = getNode().findChild(parameter.getSpecification().getName()); + if (field == null) { continue; } ExecutableTypeData type = field.getNodeData().findExecutableType(parameter.getTypeSystemType()); diff -r 1964871a642d -r 97ad6d3e7557 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java Sat Apr 20 12:16:22 2013 +0200 @@ -99,7 +99,6 @@ if (element.getModifiers().contains(Modifier.PRIVATE)) { return null; } - CodeExecutableElement executable = CodeExecutableElement.clone(getContext().getEnvironment(), element); executable.setReturnType(null); executable.setSimpleName(CodeNames.of(type.getSimpleName().toString())); diff -r 1964871a642d -r 97ad6d3e7557 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java Sat Apr 20 12:16:22 2013 +0200 @@ -27,7 +27,7 @@ import javax.lang.model.type.*; import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; +import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; public class MethodSpec { @@ -151,11 +151,11 @@ for (ParameterSpec requiredSpec : getRequired()) { b.append(sep); - if (requiredSpec.getCardinality() == Cardinality.MULTIPLE) { + if (requiredSpec.getCardinality() == Cardinality.MANY) { b.append("{"); } b.append(createTypeSignature(requiredSpec, false)); - if (requiredSpec.getCardinality() == Cardinality.MULTIPLE) { + if (requiredSpec.getCardinality() == Cardinality.MANY) { b.append("}"); } sep = ", "; diff -r 1964871a642d -r 97ad6d3e7557 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 Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Sat Apr 20 12:16:22 2013 +0200 @@ -27,14 +27,11 @@ import javax.lang.model.type.*; import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; import com.oracle.truffle.codegen.processor.template.MethodSpec.TypeDef; public class ParameterSpec { - public enum Cardinality { - ONE, MULTIPLE; - } - private final String name; private final List allowedTypes; diff -r 1964871a642d -r 97ad6d3e7557 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 Tue Apr 16 11:03:40 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java Sat Apr 20 12:16:22 2013 +0200 @@ -33,7 +33,7 @@ import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; +import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; import com.oracle.truffle.codegen.processor.typesystem.*; public abstract class TemplateMethodParser { @@ -226,7 +226,7 @@ ConsumableListIterator required = new ConsumableListIterator<>(spec.getRequired()); while (required.get() != null || types.get() != null) { if (required.get() == null || types.get() == null) { - if (required.get() != null && required.get().getCardinality() == Cardinality.MULTIPLE) { + if (required.get() != null && required.get().getCardinality() == Cardinality.MANY) { required.consume(); specificationParameterIndex = 0; continue; @@ -236,7 +236,7 @@ boolean implicit = types.getIndex() < spec.getImplicitRequiredTypes().size(); ActualParameter resolvedParameter = matchParameter(required.get(), types.get(), template, specificationParameterIndex, implicit); if (resolvedParameter == null) { - if (required.get().getCardinality() == Cardinality.MULTIPLE) { + if (required.get().getCardinality() == Cardinality.MANY) { required.consume(); continue; } @@ -248,7 +248,7 @@ if (required.get().getCardinality() == Cardinality.ONE) { required.consume(); specificationParameterIndex = 0; - } else if (required.get().getCardinality() == Cardinality.MULTIPLE) { + } else if (required.get().getCardinality() == Cardinality.MANY) { specificationParameterIndex++; } }