# HG changeset patch # User Christian Humer # Date 1366453409 -7200 # Node ID 9d29e5aa54d271dc0e80db72f9dc25ab169a4443 # Parent b69312e4eceb81cae50811f37236a3d30ca68f5b# Parent 9b455ec158209804faa330951445d394930b664c Merge. diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryNodeTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryNodeTest.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryNodeTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,6 +22,9 @@ */ package com.oracle.truffle.api.codegen.test; +import static com.oracle.truffle.api.codegen.test.TestHelper.*; +import static junit.framework.Assert.*; + import org.junit.*; import com.oracle.truffle.api.codegen.*; @@ -29,9 +32,6 @@ import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode; -import static junit.framework.Assert.*; -import static com.oracle.truffle.api.codegen.test.TestHelper.*; - public class BinaryNodeTest { @Test @@ -49,31 +49,13 @@ executeWith(node, new Object(), new Object()); } + @NodeChildren({@NodeChild("leftNode"), @NodeChild("rightNode")}) abstract static class BinaryNode extends ValueNode { - @Child protected ValueNode leftNode; - @Child protected ValueNode rightNode; - - public BinaryNode(ValueNode left, ValueNode right) { - this.leftNode = left; - this.rightNode = right; - } - - public BinaryNode(BinaryNode prev) { - this(prev.leftNode, prev.rightNode); - } } abstract static class AddNode extends BinaryNode { - public AddNode(ValueNode left, ValueNode right) { - super(left, right); - } - - public AddNode(AddNode prev) { - super(prev); - } - @Specialization int add(int left, int right) { return left + right; diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BuiltinTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BuiltinTest.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BuiltinTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -32,7 +32,6 @@ import com.oracle.truffle.api.codegen.test.BuiltinTestFactory.StrFactory.StrConcatFactory; import com.oracle.truffle.api.codegen.test.BuiltinTestFactory.StrFactory.StrLengthFactory; import com.oracle.truffle.api.codegen.test.BuiltinTestFactory.StrFactory.StrSubstrFactory; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.ChildrenNode; import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode; @@ -97,7 +96,7 @@ assertSame(context, executeWith(node)); } - @NodeClass(BuiltinNode.class) + @NodeClass(value = BuiltinNode.class, splitByMethodName = true) static class Str { private final String internal; @@ -162,23 +161,22 @@ } } - abstract static class BuiltinNode extends ChildrenNode { + @NodeChild(value = "children", type = ValueNode[].class) + abstract static class BuiltinNode extends ValueNode { protected final Context context; public BuiltinNode(BuiltinNode node) { - this(node.context, node.children); + this(node.context); } - public BuiltinNode(Context context, ValueNode... children) { - super(children); + public BuiltinNode(Context context) { this.context = context; } public Context getContext() { return context; } - } static class Context { diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/ExecuteEvaluatedTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/ExecuteEvaluatedTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,78 @@ +/* + * 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.test; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class ExecuteEvaluatedTest { + + public abstract static class ExtValueNode extends ValueNode { + + public CallTarget executeCallTarget(VirtualFrame frame) throws UnexpectedResultException { + return SimpleTypesGen.SIMPLETYPES.expectCallTarget(execute(frame)); + } + + } + + /* Represents target[element] */ + @NodeChildren({@NodeChild("targetNode"), @NodeChild("elementNode")}) + abstract static class ReadElementNode extends ExtValueNode { + + @Specialization + int getInt(Object[] target, int element) { + return (int) target[element]; + } + + public abstract Object executeWith(VirtualFrame frame, Object targetValue); + } + + /* Represents target[element]() */ + @NodeChildren({@NodeChild("targetNode"), @NodeChild(value = "elementNode", type = ReadElementNode.class, executeWith = "targetNode")}) + abstract static class ElementCallNode extends ExtValueNode { + + @Specialization + Object call(Object receiver, CallTarget callTarget) { + return callTarget.call(new TestArguments(receiver)); + } + + } + + public static class TestArguments extends Arguments { + + private final Object receiver; + + public TestArguments(Object receiver) { + this.receiver = receiver; + } + + public Object getReceiver() { + return receiver; + } + + } + +} diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/GuardsTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/GuardsTest.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/GuardsTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -30,7 +30,6 @@ import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.api.codegen.test.GuardsTestFactory.GlobalFlagGuardFactory; import com.oracle.truffle.api.codegen.test.GuardsTestFactory.InvocationGuardFactory; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.ChildrenNode; import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode; @@ -52,19 +51,12 @@ assertEquals(1, InvocationGuard.genericInvocations); } - public abstract static class InvocationGuard extends ChildrenNode { + @NodeChildren({@NodeChild("value0"), @NodeChild("value1")}) + public abstract static class InvocationGuard extends ValueNode { static int specializedInvocations = 0; static int genericInvocations = 0; - public InvocationGuard(ValueNode... children) { - super(children); - } - - public InvocationGuard(InvocationGuard node) { - super(node); - } - boolean guard(int value0, int value1) { return value0 != Integer.MAX_VALUE; } @@ -95,18 +87,11 @@ assertEquals(42, executeWith(root, NULL)); } - public abstract static class GlobalFlagGuard extends ChildrenNode { + @NodeChild("expression") + public abstract static class GlobalFlagGuard extends ValueNode { static boolean globalFlag = false; - public GlobalFlagGuard(ValueNode... children) { - super(children); - } - - public GlobalFlagGuard(GlobalFlagGuard node) { - super(node); - } - static boolean globalFlagGuard() { return globalFlag; } diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java Sat Apr 20 12:23:29 2013 +0200 @@ -26,6 +26,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.codegen.test.BuiltinTest.*; import com.oracle.truffle.api.codegen.test.TypeSystemTest.*; /** @@ -46,7 +47,7 @@ List argumentList = new ArrayList<>(); argumentList.addAll(Arrays.asList(constants)); - if (ChildrenNode.class.isAssignableFrom(factory.getNodeClass())) { + if (ChildrenNode.class.isAssignableFrom(factory.getNodeClass()) || BuiltinNode.class.isAssignableFrom(factory.getNodeClass())) { argumentList.add(argumentNodes); } else { argumentList.addAll(Arrays.asList(argumentNodes)); diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -30,41 +30,40 @@ public class TypeSystemTest { - @TypeSystem({int.class, Str.class}) + @TypeSystem({int.class, Str.class, CallTarget.class, Object[].class}) static class SimpleTypes { } @TypeSystemReference(SimpleTypes.class) - abstract static class ValueNode extends Node { + public abstract static class ValueNode extends Node { - int executeInt(VirtualFrame frame) throws UnexpectedResultException { + public int executeInt(VirtualFrame frame) throws UnexpectedResultException { return SimpleTypesGen.SIMPLETYPES.expectInteger(execute(frame)); } - Str executeStr(VirtualFrame frame) throws UnexpectedResultException { + public Str executeStr(VirtualFrame frame) throws UnexpectedResultException { return SimpleTypesGen.SIMPLETYPES.expectStr(execute(frame)); } - abstract Object execute(VirtualFrame frame); + public Object[] executeIntArray(VirtualFrame frame) throws UnexpectedResultException { + return SimpleTypesGen.SIMPLETYPES.expectObjectArray(execute(frame)); + } + + public abstract Object execute(VirtualFrame frame); + + @Override + public ValueNode copy() { + return (ValueNode) super.copy(); + } } - @TypeSystemReference(SimpleTypes.class) - abstract static class ChildrenNode extends ValueNode { - - @Children protected ValueNode[] children; - - public ChildrenNode(ValueNode... children) { - this.children = adoptChildren(children); - } - - public ChildrenNode(ChildrenNode node) { - this(node.children); - } + @NodeChild(value = "children", type = ValueNode[].class) + public abstract static class ChildrenNode extends ValueNode { } @TypeSystemReference(SimpleTypes.class) - static class TestRootNode extends RootNode { + public static class TestRootNode extends RootNode { @Child private E node; @@ -82,7 +81,7 @@ } } - static class TestArguments extends Arguments { + public static class TestArguments extends Arguments { private final Object[] values; @@ -100,7 +99,7 @@ } - static class ArgumentNode extends ValueNode { + public static class ArgumentNode extends ValueNode { final int index; @@ -109,7 +108,7 @@ } @Override - Object execute(VirtualFrame frame) { + public Object execute(VirtualFrame frame) { return ((TestArguments) frame.getArguments()).get(index); } diff -r 9b455ec15820 -r 9d29e5aa54d2 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:23:29 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 9b455ec15820 -r 9d29e5aa54d2 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:23:29 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 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeClass.java Sat Apr 20 12:23:29 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 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCast.java Sat Apr 20 12:23:29 2013 +0200 @@ -24,11 +24,6 @@ import java.lang.annotation.*; -/** - * - * - * - */ @Retention(RetentionPolicy.CLASS) @Target({ElementType.METHOD}) public @interface TypeCast { diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java Sat Apr 20 12:23:29 2013 +0200 @@ -27,6 +27,7 @@ import javax.annotation.processing.*; import javax.lang.model.element.*; +import javax.tools.Diagnostic.Kind; import com.oracle.truffle.codegen.processor.template.*; @@ -49,6 +50,7 @@ public final M parse(RoundEnvironment env, Element element) { this.roundEnv = env; + M model = null; try { AnnotationMirror mirror = null; if (getAnnotationType() != null) { @@ -58,13 +60,16 @@ if (!context.getTruffleTypes().verify(context, element, mirror)) { return null; } - M model = parse(element, mirror); + model = parse(element, mirror); if (model == null) { return null; } model.emitMessages((TypeElement) element, log); return filterErrorElements(model); + } catch (CompileErrorException e) { + log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage()); + return null; } finally { this.roundEnv = null; } diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/CompileErrorException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/CompileErrorException.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,33 @@ +/* + * 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; + +public class CompileErrorException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public CompileErrorException(String message) { + super(message); + } + +} diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java Sat Apr 20 12:23:29 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 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Sat Apr 20 12:23:29 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; } @@ -210,6 +214,8 @@ return b.toString(); case TYPEVAR: return "Any"; + case ERROR: + throw new CompileErrorException("Type error " + mirror); default: throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); } @@ -247,6 +253,8 @@ return getWildcardName((WildcardType) mirror); case TYPEVAR: return "?"; + case ERROR: + throw new CompileErrorException("Type error " + mirror); default: throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); } @@ -313,6 +321,10 @@ return "void"; case TYPEVAR: 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); } @@ -326,6 +338,10 @@ return mirror.getKind().isPrimitive(); } + public static boolean isPrimitiveOrVoid(TypeMirror mirror) { + return isPrimitive(mirror) || isVoid(mirror); + } + public static List getQualifiedSuperTypeNames(TypeElement element) { List types = getSuperTypes(element); List qualifiedNames = new ArrayList<>(); @@ -361,7 +377,7 @@ return null; } - private static List getElementHierarchy(Element e) { + public static List getElementHierarchy(Element e) { List elements = new ArrayList<>(); elements.add(e); @@ -579,7 +595,7 @@ @Override public Object visitEnumConstant(VariableElement c, Void p) { - return c.getConstantValue(); + return c; } @Override @@ -762,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; } } @@ -803,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 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java Sat Apr 20 12:23:29 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 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Sat Apr 20 12:23:29 2013 +0200 @@ -46,6 +46,11 @@ this.parent = parent; } + @Override + public String toString() { + return root.toString(); + } + public int getTreeCount() { return treeCount; } @@ -277,7 +282,13 @@ } public CodeTreeBuilder tree(CodeTree treeToAdd) { - return push((BuilderCodeTree) treeToAdd).end(); + if (treeToAdd instanceof BuilderCodeTree) { + return push((BuilderCodeTree) treeToAdd).end(); + } else { + BuilderCodeTree tree = new BuilderCodeTree(GROUP, null, null); + tree.add(treeToAdd); + return push(tree).end(); + } } public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4, String... chunks) { diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeVariable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeVariable.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,60 @@ +/* + * 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.ast; + +public class CodeTreeVariable extends CodeTree { + + private final String name; + + private CodeTree value; + + public CodeTreeVariable() { + super(CodeTreeKind.GROUP, null, null); + this.name = ""; + } + + public CodeTreeVariable(String name) { + super(CodeTreeKind.GROUP, null, null); + this.name = name; + } + + public String getName() { + return name; + } + + public void set(CodeTree tree) { + if (value == tree) { + return; + } + if (this.value != null) { + remove(this.value); + } + this.value = tree; + add(tree); + } + + public CodeTree get() { + return value; + } + +} diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java Sat Apr 20 12:23:29 2013 +0200 @@ -64,11 +64,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 @@ -83,7 +89,7 @@ @Override public List getTypeArguments() { - return Collections.emptyList(); + return typeArguments; } @Override diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java Sat Apr 20 12:23:29 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 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java Sat Apr 20 12:23:29 2013 +0200 @@ -35,8 +35,7 @@ public final class OrganizedImports { - private final Map importUsage = new HashMap<>(); - private final Map staticImportUsage = new HashMap<>(); + private final Set staticImportUsage = new HashSet<>(); private final Map simpleNamesUsed = new HashMap<>(); @@ -53,16 +52,33 @@ public static OrganizedImports organize(CodeTypeElement topLevelClass) { OrganizedImports organized = new OrganizedImports(topLevelClass); - - OrganizedImports.ReferenceCollector reference = new ReferenceCollector(); - topLevelClass.accept(reference, null); - - OrganizedImports.ImportResolver resolver = new ImportResolver(reference, organized); - topLevelClass.accept(resolver, null); + organized.organizeImpl(); return organized; } - public String useImport(TypeMirror type) { + private void organizeImpl() { + ImportTypeReferenceVisitor reference = new ImportTypeReferenceVisitor(); + topLevelClass.accept(reference, null); + + processStaticImports(topLevelClass); + List types = Utils.getSuperTypes(topLevelClass); + for (TypeElement typeElement : types) { + processStaticImports(typeElement); + } + + for (TypeMirror type : staticImportUsage) { + TypeElement element = fromTypeMirror(type); + if (element != null) { + // already processed by supertype + if (types.contains(element)) { + continue; + } + processStaticImports(element); + } + } + } + + public String createTypeReference(Element enclosedElement, TypeMirror type) { switch (type.getKind()) { case BOOLEAN: case BYTE: @@ -75,11 +91,11 @@ case VOID: return Utils.getSimpleName(type); case DECLARED: - return createDeclaredTypeName((DeclaredType) type); + return createDeclaredTypeName(enclosedElement, (DeclaredType) type); case ARRAY: - return useImport(((ArrayType) type).getComponentType()) + "[]"; + return createTypeReference(enclosedElement, ((ArrayType) type).getComponentType()) + "[]"; case WILDCARD: - return createWildcardName((WildcardType) type); + return createWildcardName(enclosedElement, (WildcardType) type); case TYPEVAR: return "?"; default: @@ -87,29 +103,50 @@ } } - private String createWildcardName(WildcardType type) { + public String createStaticFieldReference(Element enclosedElement, TypeMirror type, String fieldName) { + return createStaticReference(enclosedElement, type, fieldName, ambiguousStaticFields, declaredStaticFields); + } + + public String createStaticMethodReference(Element enclosedElement, TypeMirror type, String methodName) { + return createStaticReference(enclosedElement, type, methodName, ambiguousStaticMethods, declaredStaticMethods); + } + + private String createStaticReference(Element enclosedElement, TypeMirror type, String name, Set ambiguousSymbols, Set declaredSymbols) { + if (ambiguousSymbols.contains(name)) { + // ambiguous import + return createTypeReference(enclosedElement, type) + "." + name; + } else if (!declaredSymbols.contains(name)) { + // not imported at all + return createTypeReference(enclosedElement, type) + "." + name; + } else { + // import declared and not ambiguous + return name; + } + } + + private String createWildcardName(Element enclosedElement, WildcardType type) { StringBuilder b = new StringBuilder(); if (type.getExtendsBound() != null) { - b.append("? extends ").append(useImport(type.getExtendsBound())); + b.append("? extends ").append(createTypeReference(enclosedElement, type.getExtendsBound())); } else if (type.getSuperBound() != null) { - b.append("? super ").append(useImport(type.getExtendsBound())); + b.append("? super ").append(createTypeReference(enclosedElement, type.getExtendsBound())); } return b.toString(); } - private String createDeclaredTypeName(DeclaredType type) { + private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) { String name = type.asElement().getSimpleName().toString(); - TypeMirror usedByType = simpleNamesUsed.get(name); - if (usedByType == null) { - simpleNamesUsed.put(name, type); - usedByType = type; - } + if (needsImport(enclosedElement, type)) { + TypeMirror usedByType = simpleNamesUsed.get(name); + if (usedByType == null) { + simpleNamesUsed.put(name, type); + usedByType = type; + } - if (typeEquals(type, usedByType)) { - addUsage(type, importUsage); - } else { - name = getQualifiedName(type); + if (!typeEquals(type, usedByType)) { + name = getQualifiedName(type); + } } if (type.getTypeArguments().size() == 0) { @@ -120,7 +157,7 @@ b.append("<"); if (type.getTypeArguments().size() > 0) { for (int i = 0; i < type.getTypeArguments().size(); i++) { - b.append(useImport(type.getTypeArguments().get(i))); + b.append(createTypeReference(enclosedElement, type.getTypeArguments().get(i))); if (i < type.getTypeArguments().size() - 1) { b.append(", "); } @@ -130,44 +167,15 @@ return b.toString(); } - public String useStaticFieldImport(TypeMirror type, String fieldName) { - return useStaticImport(type, fieldName, ambiguousStaticFields, declaredStaticFields); - } - - public String useStaticMethodImport(TypeMirror type, String methodName) { - return useStaticImport(type, methodName, ambiguousStaticMethods, declaredStaticMethods); - } - - private String useStaticImport(TypeMirror type, String name, Set ambiguousSymbols, Set declaredSymbols) { - if (ambiguousSymbols.contains(name)) { - // ambiguous import - return useImport(type) + "." + name; - } else if (!declaredSymbols.contains(name)) { - // not imported at all - return useImport(type) + "." + name; - } else { - // import declared and not ambiguous - addUsage(type, staticImportUsage); - return name; - } - } - public Set generateImports() { Set imports = new HashSet<>(); - imports.addAll(generateImports(topLevelClass, importUsage.keySet())); - imports.addAll(generateStaticImports(topLevelClass, staticImportUsage.keySet())); + imports.addAll(generateImports(simpleNamesUsed.values())); + imports.addAll(generateStaticImports(staticImportUsage)); return imports; } - void clearStaticImports() { - declaredStaticFields.clear(); - declaredStaticMethods.clear(); - ambiguousStaticFields.clear(); - ambiguousStaticMethods.clear(); - } - boolean processStaticImports(TypeElement element) { Set importedMethods = new HashSet<>(); List methods = ElementFilter.methodsIn(element.getEnclosedElements()); @@ -217,37 +225,39 @@ return allAmbiguous; } - private static Set generateImports(CodeTypeElement e, Set toGenerate) { - Set autoImportedTypes = new HashSet<>(); + private boolean needsImport(Element enclosedElement, TypeMirror importType) { + String importPackagName = getPackageName(importType); + if (importPackagName == null) { + return false; + } else if (importPackagName.equals("java.lang")) { + return false; + } else if (importPackagName.equals(getPackageName(topLevelClass)) && Utils.isTopLevelClass(importType)) { + return false; // same package name -> no import + } + + List elements = Utils.getElementHierarchy(enclosedElement); - // if type is declared inside a super type of this class -> no import - collectSuperTypeImports(e, autoImportedTypes); - collectInnerTypeImports(e, autoImportedTypes); + Set autoImportedTypes = new HashSet<>(); + for (Element element : elements) { + if (element.getKind().isClass()) { + collectSuperTypeImports((TypeElement) element, autoImportedTypes); + collectInnerTypeImports((TypeElement) element, autoImportedTypes); + } + } + String qualifiedName = getQualifiedName(importType); + if (autoImportedTypes.contains(qualifiedName)) { + return false; + } + + return true; + } + + private static Set generateImports(Collection toGenerate) { TreeSet importObjects = new TreeSet<>(); for (TypeMirror importType : toGenerate) { - String importTypePackageName = getPackageName(importType); - if (importTypePackageName == null) { - continue; // no package name -> no import - } - - if (importTypePackageName.equals("java.lang")) { - continue; // java.lang is automatically imported - } - - if (importTypePackageName.equals(getPackageName(e)) && Utils.isTopLevelClass(importType)) { - continue; // same package name -> no import - } - - String qualifiedName = getQualifiedName(importType); - - if (autoImportedTypes.contains(qualifiedName)) { - continue; - } - importObjects.add(new CodeImport(importType, getQualifiedName(importType), false)); } - return importObjects; } @@ -268,12 +278,12 @@ } } - private static Set generateStaticImports(CodeTypeElement e, Set toGenerate) { + private Set generateStaticImports(Set toGenerate) { Set autoImportedStaticTypes = new HashSet<>(); // if type is declared inside a super type of this class -> no import - autoImportedStaticTypes.add(getQualifiedName(e)); - autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(e)); + autoImportedStaticTypes.add(getQualifiedName(topLevelClass)); + autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(topLevelClass)); TreeSet importObjects = new TreeSet<>(); for (TypeMirror importType : toGenerate) { @@ -292,73 +302,52 @@ return importObjects; } - private static void addUsage(TypeMirror type, Map usageMap) { - if (type != null) { - Integer value = usageMap.get(type); - if (value == null) { - usageMap.put(type, 1); - } else { - usageMap.put(type, value + 1); - } - } - } - - private static class ReferenceCollector extends CodeElementScanner { - - final Map typeReferences = new HashMap<>(); - final Map staticTypeReferences = new HashMap<>(); + private abstract static class TypeReferenceVisitor extends CodeElementScanner { @Override public void visitTree(CodeTree e, Void p) { if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) { - addStaticImport(e.getType()); + visitStaticFieldReference(e, e.getType(), e.getString()); } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) { - addStaticImport(e.getType()); - } else { - addImport(e.getType()); + visitStaticMethodReference(e, e.getType(), e.getString()); + } else if (e.getType() != null) { + visitTypeReference(e, e.getType()); } super.visitTree(e, p); } @Override public Void visitExecutable(CodeExecutableElement e, Void p) { - visitAnnotations(e.getAnnotationMirrors()); + visitAnnotations(e, e.getAnnotationMirrors()); if (e.getReturnType() != null) { - addImport(e.getReturnType()); + visitTypeReference(e, e.getReturnType()); } for (TypeMirror type : e.getThrownTypes()) { - addImport(type); + visitTypeReference(e, type); } return super.visitExecutable(e, p); } @Override public Void visitType(CodeTypeElement e, Void p) { - visitAnnotations(e.getAnnotationMirrors()); + visitAnnotations(e, e.getAnnotationMirrors()); - addImport(e.getSuperclass()); + visitTypeReference(e, e.getSuperclass()); for (TypeMirror type : e.getImplements()) { - addImport(type); + visitTypeReference(e, type); } return super.visitType(e, p); } - @Override - public Void visitVariable(VariableElement f, Void p) { - visitAnnotations(f.getAnnotationMirrors()); - addImport(f.asType()); - return super.visitVariable(f, p); - } - - private void visitAnnotations(List mirrors) { + private void visitAnnotations(Element enclosingElement, List mirrors) { for (AnnotationMirror mirror : mirrors) { - visitAnnotation(mirror); + visitAnnotation(enclosingElement, mirror); } } - public void visitAnnotation(AnnotationMirror e) { - addImport(e.getAnnotationType()); + public void visitAnnotation(Element enclosingElement, AnnotationMirror e) { + visitTypeReference(enclosingElement, e.getAnnotationType()); if (!e.getElementValues().isEmpty()) { Map values = e.getElementValues(); Set methodsSet = values.keySet(); @@ -372,17 +361,23 @@ for (int i = 0; i < methodsList.size(); i++) { AnnotationValue value = values.get(methodsList.get(i)); - visitAnnotationValue(value); + visitAnnotationValue(enclosingElement, value); } } } - public void visitAnnotationValue(AnnotationValue e) { - e.accept(new AnnotationValueReferenceVisitor(), null); + public void visitAnnotationValue(Element enclosingElement, AnnotationValue e) { + e.accept(new AnnotationValueReferenceVisitor(enclosingElement), null); } private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7 { + private final Element enclosingElement; + + public AnnotationValueReferenceVisitor(Element enclosedElement) { + this.enclosingElement = enclosedElement; + } + @Override public Void visitBoolean(boolean b, Void p) { return null; @@ -430,95 +425,67 @@ @Override public Void visitType(TypeMirror t, Void p) { - addImport(t); + visitTypeReference(enclosingElement, t); return null; } @Override public Void visitEnumConstant(VariableElement c, Void p) { - addImport(c.asType()); + visitTypeReference(enclosingElement, c.asType()); return null; } @Override public Void visitAnnotation(AnnotationMirror a, Void p) { - ReferenceCollector.this.visitAnnotation(a); + TypeReferenceVisitor.this.visitAnnotation(enclosingElement, a); return null; } @Override public Void visitArray(List vals, Void p) { for (int i = 0; i < vals.size(); i++) { - ReferenceCollector.this.visitAnnotationValue(vals.get(i)); + TypeReferenceVisitor.this.visitAnnotationValue(enclosingElement, vals.get(i)); } return null; } } @Override + public Void visitVariable(VariableElement f, Void p) { + visitAnnotations(f, f.getAnnotationMirrors()); + visitTypeReference(f, f.asType()); + return super.visitVariable(f, p); + } + + @Override public void visitImport(CodeImport e, Void p) { } - private void addStaticImport(TypeMirror type) { - addUsage(type, staticTypeReferences); + public abstract void visitTypeReference(Element enclosedType, TypeMirror type); + + public abstract void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName); + + public abstract void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName); + + } + + private class ImportTypeReferenceVisitor extends TypeReferenceVisitor { + + @Override + public void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName) { + staticImportUsage.add(type); } - private void addImport(TypeMirror type) { - addUsage(type, typeReferences); + @Override + public void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName) { + staticImportUsage.add(type); + } + + @Override + public void visitTypeReference(Element enclosedType, TypeMirror type) { + createTypeReference(enclosedType, type); } } - private static class ImportResolver extends CodeElementScanner { - - private final ReferenceCollector collector; - private final OrganizedImports organizedImports; - - public ImportResolver(OrganizedImports.ReferenceCollector collector, OrganizedImports organizedImports) { - this.collector = collector; - this.organizedImports = organizedImports; - } - - @Override - public Void visitType(CodeTypeElement e, Void p) { - if (e.isTopLevelClass()) { - organizedImports.clearStaticImports(); - - organizedImports.processStaticImports(e); - List types = Utils.getSuperTypes(e); - for (TypeElement typeElement : types) { - organizedImports.processStaticImports(typeElement); - } - - for (TypeMirror type : collector.staticTypeReferences.keySet()) { - TypeElement element = fromTypeMirror(type); - if (element != null) { - // already processed by supertype - if (types.contains(element)) { - continue; - } - organizedImports.processStaticImports(element); - } - } - - for (TypeMirror imp : collector.typeReferences.keySet()) { - organizedImports.useImport(imp); - } - } - return super.visitType(e, p); - } - - @Override - public void visitTree(CodeTree e, Void p) { - if (e.getCodeKind() == CodeTreeKind.TYPE) { - organizedImports.useImport(e.getType()); - } else if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) { - organizedImports.useStaticFieldImport(e.getType(), e.getString()); - } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) { - organizedImports.useStaticMethodImport(e.getType(), e.getString()); - } - super.visitTree(e, p); - } - } - } diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.truffle.codegen.processor.node; +import java.util.*; + import javax.lang.model.element.*; import com.oracle.truffle.codegen.processor.*; @@ -59,6 +61,47 @@ return getMethod().getModifiers().contains(Modifier.FINAL); } + public boolean isAbstract() { + return getMethod().getModifiers().contains(Modifier.ABSTRACT); + } + + public int getEvaluatedCount() { + int count = 0; + for (ActualParameter parameter : getParameters()) { + if (parameter.getSpecification().isSignature()) { + count++; + } + } + return count; + } + + public boolean startsWithSignature(TemplateMethod method) { + for (ActualParameter param : getParameters()) { + if (!param.getSpecification().isSignature()) { + continue; + } + ActualParameter foundParam = method.findParameter(param.getLocalName()); + if (foundParam != null) { + TypeData actualType = param.getTypeSystemType(); + TypeData foundType = foundParam.getTypeSystemType(); + if (actualType == null || foundType == null || !actualType.equalsType(foundType)) { + return false; + } + } + } + return true; + } + + public boolean hasGenericSignature() { + List types = getSignature(); + for (TypeData typeData : types) { + if (!typeData.isGeneric()) { + return false; + } + } + return true; + } + @Override public int hashCode() { return type.hashCode(); diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java Sat Apr 20 12:23:29 2013 +0200 @@ -29,6 +29,7 @@ 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.typesystem.*; @@ -42,27 +43,37 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - - List types = new ArrayList<>(); - types.addAll(getNode().getTypeSystem().getPrimitiveTypeMirrors()); - types.add(getContext().getType(void.class)); - - ParameterSpec returnTypeSpec = new ParameterSpec("executedValue", types); - returnTypeSpec.setSignature(true); - MethodSpec spec = new MethodSpec(returnTypeSpec); - spec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame())); + MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null); + spec.setVariableRequiredArguments(true); + ParameterSpec other = new ParameterSpec("other", nodeTypeMirrors(getNode())); + other.setCardinality(Cardinality.MANY); + other.setSignature(true); + other.setIndexed(true); + spec.addRequired(other); return spec; } @Override public final boolean isParsable(ExecutableElement method) { - boolean parsable = method.getSimpleName().toString().startsWith("execute"); - return parsable; + if (method.getModifiers().contains(Modifier.STATIC)) { + return false; + } else if (method.getModifiers().contains(Modifier.NATIVE)) { + return false; + } + return method.getSimpleName().toString().startsWith("execute"); + } + + @Override + protected List nodeTypeMirrors(NodeData nodeData) { + // executable types not yet available + List types = new ArrayList<>(nodeData.getTypeSystem().getPrimitiveTypeMirrors()); + types.add(nodeData.getTypeSystem().getVoidType().getPrimitiveType()); + return types; } @Override public ExecutableTypeData create(TemplateMethod method) { - TypeData resolvedType = method.getReturnType().getActualTypeData(getNode().getTypeSystem()); + TypeData resolvedType = method.getReturnType().getTypeSystemType(); return new ExecutableTypeData(method, getNode().getTypeSystem(), resolvedType); } diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java Sat Apr 20 12:23:29 2013 +0200 @@ -40,7 +40,7 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return createDefaultMethodSpec(method, mirror, null); + return createDefaultMethodSpec(method, mirror, true, null); } @Override diff -r 9b455ec15820 -r 9d29e5aa54d2 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:23:29 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 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Sat Apr 20 12:23:29 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.*; @@ -88,11 +88,12 @@ continue; } - method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(parameter))); + method.addParameter(new CodeVariableElement(parameter.getType(), valueName(parameter))); } } - private static void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeImplicit) { + private static void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, + boolean includeImplicit) { if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { builder.string("frameValue"); } @@ -109,14 +110,33 @@ continue; } + ActualParameter sourceParameter = source.findParameter(parameter.getLocalName()); + if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) { - builder.cast(parameter.getActualType(), CodeTreeBuilder.singleString("ex.getResult()")); + builder.cast(parameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); + } else if (sourceParameter != null) { + builder.string(valueName(sourceParameter, parameter)); } else { builder.string(valueName(parameter)); } } } + private static String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) { + if (sourceParameter != null) { + if (!sourceParameter.getSpecification().isSignature()) { + return valueName(targetParameter); + } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) { + if (sourceParameter.getTypeSystemType().needsCastTo(targetParameter.getTypeSystemType())) { + return castValueName(targetParameter); + } + } + return valueName(targetParameter); + } else { + return valueName(targetParameter); + } + } + private static CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) { CodeTreeBuilder builder = parent.create(); @@ -129,7 +149,6 @@ } TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); NodeData node = (NodeData) targetMethod.getTemplate(); - TypeSystemData typeSystem = node.getTypeSystem(); boolean accessible = targetMethod.canBeAccessedByInstanceOf(node.getNodeType()); if (accessible) { @@ -140,7 +159,11 @@ builder.string(THIS_NODE_LOCAL_VAR_NAME); } } else { - builder.string("super"); + if (targetMethod instanceof ExecutableTypeData) { + builder.string("this"); + } else { + builder.string("super"); + } } } else { if (method.getModifiers().contains(STATIC)) { @@ -156,17 +179,8 @@ ActualParameter sourceParameter = sourceMethod.findParameter(parameter.getLocalName()); assert parameter != null; - if (castedValues) { - NodeFieldData field = node.findField(parameter.getSpecification().getName()); - if (field == null) { - builder.string(valueName(parameter)); - } else { - if (Utils.typeEquals(sourceParameter.getActualType(), parameter.getActualType())) { - builder.string(valueName(parameter)); - } else { - builder.string(castValueName(parameter)); - } - } + if (castedValues && sourceParameter != null) { + builder.string(valueName(sourceParameter, parameter)); } else { builder.string(valueName(parameter)); } @@ -180,7 +194,7 @@ if (valueParameter == null) { valueParameter = targetParameter; } - TypeData targetType = targetParameter.getActualTypeData(typeSystem); + TypeData targetType = targetParameter.getTypeSystemType(); if (targetParameter.isImplicit() || valueParameter.isImplicit()) { continue; @@ -188,7 +202,7 @@ TypeData valueType = null; if (valueParameter != null) { - valueType = valueParameter.getActualTypeData(typeSystem); + valueType = valueParameter.getTypeSystemType(); } if (targetParameter.getSpecification().isLocal()) { @@ -203,7 +217,15 @@ } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) { builder.string("ex.getResult()"); } else if (targetType == null || targetType.isGeneric() || (valueType != null && valueType.equalsType(targetType))) { + builder.startGroup(); + + if (valueType != null && sourceMethod.getMethodName().equals(targetMethod.getMethodName()) && !valueType.isGeneric() && targetType.isGeneric()) { + builder.string("("); + builder.type(targetType.getPrimitiveType()); + builder.string(") "); + } builder.string(valueName(targetParameter)); + builder.end(); } else { builder.string(castValueName(targetParameter)); } @@ -214,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) { @@ -243,10 +271,10 @@ return prefix; } - private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, String value) { + private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, CodeTree value) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); startCallTypeSystemMethod(context, builder, node, methodName); - builder.string(value); + builder.tree(value); builder.end().end(); return builder.getRoot(); } @@ -277,11 +305,11 @@ 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; } - TypeData typeData = parameter.getActualTypeData(node.getTypeSystem()); + TypeData typeData = parameter.getTypeSystemType(); if (typeData != null && !typeData.isGeneric()) { valuesNeedsCast.add(parameter.getLocalName()); } @@ -344,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.FIELD) { + NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName()); + if (field == null) { continue; } ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); @@ -369,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.FIELD) { + NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName()); + if (field == null) { continue; } ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); @@ -388,12 +416,12 @@ 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); - TypeData targetType = target.getActualTypeData(node.getTypeSystem()); - TypeData sourceType = source.getActualTypeData(node.getTypeSystem()); + TypeData targetType = target.getTypeSystemType(); + TypeData sourceType = source.getTypeSystemType(); if (targetType.equalsType(sourceType) || targetType.isGeneric()) { return null; @@ -409,7 +437,7 @@ builder.string(" || "); } - startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getActualTypeData(node.getTypeSystem()))); + startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getTypeSystemType())); builder.string(valueName(source)); builder.end().end(); // call @@ -422,14 +450,12 @@ 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(); - TypeSystemData typeSystem = node.getTypeSystem(); + TypeData sourceType = source.getTypeSystemType(); + TypeData targetType = target.getTypeSystemType(); - TypeData sourceType = source.getActualTypeData(typeSystem); - TypeData targetType = target.getActualTypeData(typeSystem); - - if (targetType.equalsType(sourceType) || targetType.isGeneric()) { + if (!sourceType.needsCastTo(targetType)) { return null; } @@ -440,9 +466,9 @@ condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); } - CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), valueName(target)); + CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), CodeTreeBuilder.singleString(valueName(target))); - return createLazyAssignment(parent, castValueName(target), target.getActualType(), condition, value); + return createLazyAssignment(parent, castValueName(target), target.getType(), condition, value); } /** @@ -483,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); } } @@ -511,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; @@ -565,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) { @@ -583,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())); @@ -616,7 +767,7 @@ } } - List children = node.getNodeChildren(); + List children = node.getNodeDeclaringChildren(); if (node.getParent() == null && children.size() > 0) { clazz.add(createGetFactories(node)); } @@ -624,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)); } @@ -656,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(); @@ -667,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.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); @@ -706,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) { @@ -785,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) { @@ -830,7 +978,7 @@ } private ExecutableElement createGetFactories(NodeData node) { - List children = node.getNodeChildren(); + List children = node.getNodeDeclaringChildren(); if (node.needsFactory()) { children.add(node); } @@ -851,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"); @@ -884,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")); @@ -942,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); @@ -954,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); @@ -992,7 +1130,7 @@ } private List createGeneratedGenericMethod(NodeData node) { - TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getActualType(); + TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); if (node.needsRewrites(context)) { List methods = new ArrayList<>(); @@ -1037,7 +1175,7 @@ nextBuilder.startReturn().startCall(generatedGenericMethodName(next)); nextBuilder.string(THIS_NODE_LOCAL_VAR_NAME); - addInternalValueParameterNames(nextBuilder, next, null, true, true); + addInternalValueParameterNames(nextBuilder, next, next, null, true, true); nextBuilder.end().end(); invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, true, invokeMethod, nextBuilder.getRoot()); @@ -1069,7 +1207,7 @@ builder.startReturn().startCall(generatedGenericMethodName(exception.getTransitionTo())); builder.string(THIS_NODE_LOCAL_VAR_NAME); - addInternalValueParameterNames(builder, exception.getTransitionTo(), null, true, true); + addInternalValueParameterNames(builder, exception.getTransitionTo(), exception.getTransitionTo(), null, true, true); builder.end().end(); } builder.end(); @@ -1080,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; } @@ -1108,20 +1253,14 @@ if (execType.isFinal()) { continue; } - CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); - if (method.getParameters().size() == 1) { - CodeVariableElement var = CodeVariableElement.clone(method.getParameters().get(0)); - var.setName("frameValue"); - method.getParameters().set(0, var); - } - method.getModifiers().remove(Modifier.ABSTRACT); - clazz.add(method); - - TypeData primaryType = specialization.getReturnType().getActualTypeData(node.getTypeSystem()); - if (primaryType == execType.getType()) { - buildFunctionalExecuteMethod(method.createBuilder(), specialization); + CodeExecutableElement executeMethod = createExecutableTypeOverride(execType); + clazz.add(executeMethod); + CodeTreeBuilder builder = executeMethod.createBuilder(); + CodeTree result = createExecuteBody(builder, specialization, execType); + if (result != null) { + builder.tree(result); } else { - buildCastingExecuteMethod(method.createBuilder(), specialization, execType.getType()); + clazz.remove(executeMethod); } } @@ -1130,23 +1269,111 @@ } } - private void buildCastingExecuteMethod(CodeTreeBuilder builder, SpecializationData specialization, TypeData type) { + private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) { + TypeData primaryType = specialization.getReturnType().getTypeSystemType(); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + ExecutableTypeData foundEvaluatedPrimaryType = findFunctionalExecutableType(specialization, execType.getEvaluatedCount()); + + if (execType == foundEvaluatedPrimaryType || foundEvaluatedPrimaryType == null) { + builder.tree(createFunctionalExecute(builder, specialization, execType)); + } else if (needsCastingExecuteMethod(execType, primaryType)) { + builder.tree(createCastingExecute(builder, specialization, execType, foundEvaluatedPrimaryType)); + } else { + return null; + } + + return builder.getRoot(); + } + + private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType) { + CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); + + int i = 0; + for (VariableElement param : method.getParameters()) { + CodeVariableElement var = CodeVariableElement.clone(param); + var.setName(valueName(execType.getParameters().get(i))); + method.getParameters().set(i, var); + i++; + } + + method.getAnnotationMirrors().clear(); + method.getModifiers().remove(Modifier.ABSTRACT); + return method; + } + + private boolean needsCastingExecuteMethod(ExecutableTypeData execType, TypeData primaryType) { + if (execType.isAbstract()) { + return true; + } + if (Utils.isPrimitiveOrVoid(primaryType.getPrimitiveType()) && Utils.isPrimitiveOrVoid(execType.getType().getPrimitiveType())) { + return true; + } + if (execType.getType().isGeneric()) { + return true; + } + return false; + } + + private ExecutableTypeData findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) { + TypeData primaryType = specialization.getReturnType().getTypeSystemType(); + List otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount); + + List filteredTypes = new ArrayList<>(); + for (ExecutableTypeData compareType : otherTypes) { + if (!Utils.typeEquals(compareType.getType().getPrimitiveType(), primaryType.getPrimitiveType())) { + continue; + } + filteredTypes.add(compareType); + } + + for (ExecutableTypeData compareType : filteredTypes) { + if (compareType.startsWithSignature(specialization)) { + return compareType; + } + } + + for (ExecutableTypeData compareType : otherTypes) { + if (compareType.startsWithSignature(specialization)) { + return compareType; + } + } + + return null; + } + + private CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) { + TypeData type = executable.getType(); + CodeTreeBuilder builder = new CodeTreeBuilder(parent); NodeData node = specialization.getNode(); - TypeSystemData typeSystem = node.getTypeSystem(); ExecutableTypeData castedType = node.findExecutableType(type); - TypeData primaryType = specialization.getReturnType().getActualTypeData(typeSystem); - ExecutableTypeData execType = specialization.getNode().findExecutableType(primaryType); + TypeData primaryType = castExecutable.getType(); - boolean needsTry = execType.hasUnexpectedValue(getContext()); + boolean needsTry = castExecutable.hasUnexpectedValue(getContext()); boolean returnVoid = type.isVoid(); - CodeTree primaryExecuteCall = null; + List executeParameters = new ArrayList<>(); + for (ActualParameter sourceParameter : executable.getParameters()) { + NodeChildData field = specialization.getNode().findChild(sourceParameter.getSpecification().getName()); + if (field == null) { + continue; + } - CodeTreeBuilder executeBuilder = CodeTreeBuilder.createBuilder(); - buildExecute(executeBuilder, null, null, execType); - primaryExecuteCall = executeBuilder.getRoot(); + ActualParameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName()); + if (targetParameter != null) { + TypeData sourceType = sourceParameter.getTypeSystemType(); + TypeData targetType = targetParameter.getTypeSystemType(); + if (sourceType.needsCastTo(targetType)) { + executeParameters.add(targetParameter); + } + } + } + builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null, true)); + + CodeTree primaryExecuteCall = createTemplateMethodCall(builder, executable, castExecutable, null); if (needsTry) { if (!returnVoid) { builder.declaration(primaryType.getPrimitiveType(), "value"); @@ -1186,6 +1413,8 @@ builder.end(); } } + + return builder.getRoot(); } private CodeTree createExpectType(NodeData node, ExecutableTypeData castedType, CodeTree value) { @@ -1211,25 +1440,28 @@ return builder.getRoot(); } - private void buildFunctionalExecuteMethod(CodeTreeBuilder builder, SpecializationData specialization) { + private CodeTree createFunctionalExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); if (specialization.isUninitialized()) { builder.tree(createDeoptimize(builder)); } - builder.tree(createExecuteChildren(builder, specialization)); + builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null, false)); CodeTree executeNode; if (specialization.isUninitialized()) { - builder.tree(createSpecializeCall(builder, specialization)); + builder.tree(createSpecializeCall(builder, executable, specialization)); } - executeNode = createExecute(builder, specialization); + executeNode = createExecute(builder, executable, specialization); SpecializationData next = specialization.findNextSpecialization(); CodeTree returnSpecialized = null; if (next != null) { - returnSpecialized = createReturnSpecializeAndExecute(builder, next, null); + returnSpecialized = createReturnSpecializeAndExecute(builder, executable, next, null); } builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized)); + + return builder.getRoot(); } private CodeTree createDeoptimize(CodeTreeBuilder parent) { @@ -1240,7 +1472,7 @@ return builder.getRoot(); } - private CodeTree createSpecializeCall(CodeTreeBuilder parent, SpecializationData specialization) { + private CodeTree createSpecializeCall(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { NodeData node = specialization.getNode(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); @@ -1252,7 +1484,7 @@ builder.startCall(factoryClassName(node), "specialize"); builder.string("this"); builder.typeLiteral(builder.findMethod().getEnclosingElement().asType()); - addInternalValueParameterNames(builder, specialization, null, true, true); + addInternalValueParameterNames(builder, executable, specialization, null, true, true); builder.end(); // call replace, call specialize } else { builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end(); @@ -1261,19 +1493,20 @@ return builder.getRoot(); } - private CodeTree createExecute(CodeTreeBuilder parent, SpecializationData specialization) { + private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { NodeData node = specialization.getNode(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); if (!specialization.getExceptions().isEmpty()) { builder.startTryBlock(); } + CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); if (specialization.isUninitialized()) { String genericMethodName = generatedGenericMethodName(null); - builder.startReturn().startCall(factoryClassName(node), genericMethodName); - builder.string("this"); - addInternalValueParameterNames(builder, specialization, null, true, true); - builder.end().end(); + returnBuilder.startCall(factoryClassName(node), genericMethodName); + returnBuilder.string("this"); + addInternalValueParameterNames(returnBuilder, executable, specialization, null, true, true); + returnBuilder.end(); } else if (specialization.getMethod() == null && !node.needsRewrites(context)) { emitEncounteredSynthetic(builder); } else if (specialization.isGeneric()) { @@ -1284,36 +1517,81 @@ genericMethodName = generatedGenericMethodName(null); } - builder.startReturn().startCall(factoryClassName(node), genericMethodName); - builder.string("this"); - addInternalValueParameterNames(builder, specialization, null, true, true); - builder.end().end(); + returnBuilder.startCall(factoryClassName(node), genericMethodName); + returnBuilder.string("this"); + addInternalValueParameterNames(returnBuilder, executable, specialization, null, true, true); + returnBuilder.end(); } else { + returnBuilder.tree(createTemplateMethodCall(returnBuilder, executable, specialization, null)); + } + + if (!returnBuilder.isEmpty()) { builder.startReturn(); - builder.tree(createTemplateMethodCall(builder, specialization, specialization, null)); - builder.end(); // return + + TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType()); + TypeData sourceType = specialization.getReturnType().getTypeSystemType(); + + if (targetType == null || sourceType == null) { + builder.tree(returnBuilder.getRoot()); + } else if (sourceType.needsCastTo(targetType)) { + builder.tree(createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.expectTypeMethodName(targetType), returnBuilder.getRoot())); + } else { + builder.tree(returnBuilder.getRoot()); + } + builder.end(); } if (!specialization.getExceptions().isEmpty()) { for (SpecializationThrowsData exception : specialization.getExceptions()) { builder.end().startCatchBlock(exception.getJavaClass(), "ex"); - builder.tree(createReturnSpecializeAndExecute(parent, exception.getTransitionTo(), null)); + builder.tree(createReturnSpecializeAndExecute(parent, executable, exception.getTransitionTo(), null)); } builder.end(); } return builder.getRoot(); } - private CodeTree createExecuteChildren(CodeTreeBuilder parent, SpecializationData specialization) { + private CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List targetParameters, + ActualParameter unexpectedParameter, boolean cast) { + NodeData sourceNode = specialization.getNode(); + CodeTreeBuilder builder = new CodeTreeBuilder(parent); - for (ActualParameter parameter : specialization.getParameters()) { - NodeFieldData field = specialization.getNode().findField(parameter.getSpecification().getName()); - if (field == null || field.getKind() == FieldKind.FIELD) { + for (ActualParameter targetParameter : targetParameters) { + NodeChildData field = sourceNode.findChild(targetParameter.getSpecification().getName()); + if (field == null) { continue; } + TypeData targetType = targetParameter.getTypeSystemType(); - buildFieldExecute(builder, specialization, parameter, field, null); + ExecutableTypeData targetExecutable = field.getNodeData().findExecutableType(targetType); + + ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); + + String targetVariableName = null; + CodeTree executionExpression = null; + if (cast || sourceParameter != null) { + TypeData sourceType = sourceParameter.getTypeSystemType(); + if (!sourceType.needsCastTo(targetType)) { + if (field.isShortCircuit() && sourceParameter != null) { + builder.tree(createShortCircuitValue(builder, sourceExecutable, specialization, field, targetParameter.getPreviousParameter(), unexpectedParameter)); + } + continue; + } + executionExpression = createExpectType(sourceNode, targetExecutable, CodeTreeBuilder.singleString(valueName(targetParameter))); + targetVariableName = castValueName(targetParameter); + } else if (sourceParameter == null) { + targetVariableName = valueName(targetParameter); + executionExpression = createExecuteChildExpression(builder, field, targetParameter); + } + + CodeTreeVariable executionVar = new CodeTreeVariable(); + CodeTree shortCircuitTree = createShortCircuitTree(builder, executionVar, targetVariableName, sourceExecutable, specialization, targetParameter, unexpectedParameter); + CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpression, targetVariableName, specialization, sourceExecutable, targetExecutable, targetParameter, + shortCircuitTree != executionVar); + + executionVar.set(unexpectedTree); + builder.tree(shortCircuitTree); } return builder.getRoot(); } @@ -1326,62 +1604,63 @@ } } - private void buildFieldExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field, ActualParameter exceptionParam) { - boolean shortCircuit = startShortCircuit(builder, specialization, param, exceptionParam); - ExecutableTypeData execType = field.getNodeData().findExecutableType(param.getActualTypeData(field.getNodeData().getTypeSystem())); - boolean unexpected = execType.hasUnexpectedValue(getContext()); + private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ExecutableTypeData currentExecutable, + ExecutableTypeData targetExecutable, ActualParameter param, boolean shortCircuit) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + boolean unexpected = targetExecutable.hasUnexpectedValue(getContext()); + builder.startStatement(); - if (!shortCircuit && unexpected) { - builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).end(); + if (!shortCircuit) { + builder.type(param.getType()).string(" ").string(targetVariableName); } if (unexpected) { + if (!shortCircuit) { + builder.end(); + } builder.startTryBlock(); + builder.startStatement(); + builder.string(targetVariableName); + } else if (shortCircuit) { + builder.startStatement(); + builder.string(targetVariableName); } - - if (!shortCircuit && !unexpected) { - builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).string(" = "); - } else { - builder.startStatement().string(valueName(param)).string(" = "); - } - buildExecute(builder, param, field, execType); + builder.string(" = "); + builder.tree(body); builder.end(); if (unexpected) { builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); SpecializationData generic = specialization.getNode().getGenericSpecialization(); - boolean execute = false; - for (ActualParameter exParam : generic.getParameters()) { - NodeFieldData exField = generic.getNode().findField(exParam.getSpecification().getName()); - if (exField == null || field.getKind() == FieldKind.FIELD) { - continue; - } - if (execute) { - buildFieldExecute(builder, specialization.getNode().getGenericSpecialization(), exParam, exField, param); - } else if (exParam.getLocalName().equals(param.getLocalName())) { - execute = true; - } - } - builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param)); + ActualParameter genericParameter = generic.findParameter(param.getLocalName()); + + List genericParameters = generic.getParametersAfter(genericParameter); + builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false)); + builder.tree(createReturnSpecializeAndExecute(builder, currentExecutable, specialization.findNextSpecialization(), param)); builder.end(); // catch block } - endShortCircuit(builder, shortCircuit); - builder.newLine(); + return builder.getRoot(); } - private void buildExecute(CodeTreeBuilder builder, ActualParameter parameter, NodeFieldData field, ExecutableTypeData execType) { - if (field != null) { - Element accessElement = field.getAccessElement(); - if (accessElement.getKind() == ElementKind.METHOD) { + 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 == 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()); } else { throw new AssertionError(); } - if (parameter.getSpecification().isIndexed()) { - builder.string("[" + parameter.getIndex() + "]"); + if (sourceParameter.getSpecification().isIndexed()) { + builder.string("[" + sourceParameter.getIndex() + "]"); } builder.string("."); } @@ -1390,22 +1669,40 @@ builder.string("frameValue"); } builder.end(); + return builder.getRoot(); } - private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) { - NodeFieldData forField = specialization.getNode().findField(parameter.getSpecification().getName()); + private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, ExecutableTypeData currentExecutable, SpecializationData specialization, + ActualParameter parameter, ActualParameter exceptionParam) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName()); if (forField == null) { - return false; + return body; } if (forField.getExecutionKind() != ExecutionKind.SHORT_CIRCUIT) { - return false; + return body; } ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter); + builder.tree(createShortCircuitValue(builder, currentExecutable, specialization, forField, shortCircuitParam, exceptionParam)); + + builder.declaration(parameter.getType(), targetVariableName, CodeTreeBuilder.createBuilder().defaultValue(parameter.getType())); + builder.startIf().string(shortCircuitParam.getLocalName()).end(); + builder.startBlock(); + builder.tree(body); + builder.end(); + + return builder.getRoot(); + } + + 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; @@ -1414,51 +1711,36 @@ } } - builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); + builder.startStatement().type(shortCircuitParam.getType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex); - - builder.tree(createTemplateMethodCall(builder, shortCircuitData, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); - + builder.tree(createTemplateMethodCall(builder, currentExecutable, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); builder.end(); // statement - builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType())); - builder.startIf().string(shortCircuitParam.getLocalName()).end(); - builder.startBlock(); - - return true; + return builder.getRoot(); } - private void endShortCircuit(CodeTreeBuilder builder, boolean shortCircuit) { - if (shortCircuit) { - builder.end(); - } - } - - private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ActualParameter exceptionParam) { + private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData nextSpecialization, ActualParameter exceptionParam) { CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); specializeCall.startCall("specializeAndExecute"); specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class"); - addInternalValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true); + addInternalValueParameterNames(specializeCall, executable, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, + true); specializeCall.end().end(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); builder.startReturn(); - builder.tree(specializeCall.getRoot()); + builder.tree(createExpectType(nextSpecialization.getNode(), executable, specializeCall.getRoot())); builder.end(); + return builder.getRoot(); } private void buildSpecializeAndExecute(CodeTypeElement clazz, SpecializationData specialization) { NodeData node = specialization.getNode(); - TypeData returnType = specialization.getReturnType().getActualTypeData(node.getTypeSystem()); - ExecutableTypeData returnExecutableType = node.findExecutableType(returnType); - boolean canThrowUnexpected = returnExecutableType == null ? true : returnExecutableType.hasUnexpectedValue(getContext()); + TypeData returnType = node.getGenericSpecialization().getReturnType().getTypeSystemType(); CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), returnType.getPrimitiveType(), "specializeAndExecute"); method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); - if (canThrowUnexpected) { - method.addThrownType(getUnexpectedValueException()); - } addInternalValueParameters(method, specialization.getNode().getGenericSpecialization(), true); clazz.add(method); @@ -1470,7 +1752,7 @@ builder.startStatement(); builder.startCall("replace"); builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState"); - addInternalValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, true, true); + addInternalValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), specialization.getNode().getGenericSpecialization(), null, true, true); builder.end(); builder.end(); // call replace builder.end(); // statement @@ -1486,10 +1768,10 @@ CodeTreeBuilder genericExecute = CodeTreeBuilder.createBuilder(); genericExecute.startCall(factoryClassName(specialization.getNode()), generatedMethodName); genericExecute.string("this"); - addInternalValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), null, true, true); + addInternalValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), specialization.getNode().getGenericSpecialization(), null, true, true); genericExecute.end(); // call generated generic - CodeTree genericInvocation = createExpectType(node, returnExecutableType, genericExecute.getRoot()); + CodeTree genericInvocation = genericExecute.getRoot(); if (generatedGeneric != null && Utils.isVoid(generatedGeneric.getReturnType())) { builder.statement(genericInvocation); diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Sat Apr 20 12:23:29 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,17 +36,18 @@ 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; private List specializations; private List specializationListeners; - private List guards; - private List executableTypes; + private Map> executableTypes; private List shortCircuits; public NodeData(TypeElement type, String id) { @@ -59,53 +59,66 @@ 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; this.specializationListeners = splitSource.specializationListeners; - this.guards = splitSource.guards; 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); - } - if (guards != null) { - children.addAll(guards); + containerChildren.addAll(specializationListeners); } if (executableTypes != null) { - children.addAll(executableTypes); + 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() { @@ -131,6 +144,10 @@ if (specializations == null) { return false; } + if (getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { + return false; + } + boolean noSpecialization = true; for (SpecializationData specialization : specializations) { noSpecialization = noSpecialization && specialization.isGeneric() || specialization.isUninitialized(); @@ -139,27 +156,29 @@ } public boolean supportsFrame() { - for (ExecutableTypeData execType : executableTypes) { - if (execType.findParameter("frameValue") == null) { - return false; + if (executableTypes != null) { + for (ExecutableTypeData execType : getExecutableTypes(-1)) { + if (execType.findParameter("frameValue") == null) { + return false; + } } } 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; @@ -170,8 +189,8 @@ return declaringNode; } - public List getDeclaredChildren() { - return declaredChildren; + public List getDeclaredNodes() { + return declaredNodes; } public void setNodeType(TypeMirror nodeType) { @@ -218,9 +237,21 @@ return null; } + public List getExecutableTypes(int evaluatedCount) { + if (evaluatedCount == -1) { + List typeData = new ArrayList<>(); + for (int currentEvaluationCount : executableTypes.keySet()) { + typeData.addAll(executableTypes.get(currentEvaluationCount)); + } + return typeData; + } else { + return executableTypes.get(evaluatedCount); + } + } + public List findGenericExecutableTypes(ProcessorContext context) { List types = new ArrayList<>(); - for (ExecutableTypeData type : executableTypes) { + for (ExecutableTypeData type : getExecutableTypes(0)) { if (!type.hasUnexpectedValue(context)) { types.add(type); } @@ -229,7 +260,7 @@ } public ExecutableTypeData findExecutableType(TypeData prmitiveType) { - for (ExecutableTypeData type : executableTypes) { + for (ExecutableTypeData type : getExecutableTypes(0)) { if (Utils.typeEquals(type.getType().getPrimitiveType(), prmitiveType.getPrimitiveType())) { return type; } @@ -240,7 +271,7 @@ public SpecializationData findUniqueSpecialization(TypeData type) { SpecializationData result = null; for (SpecializationData specialization : specializations) { - if (specialization.getReturnType().getActualTypeData(getTypeSystem()) == type) { + if (specialization.getReturnType().getTypeSystemType() == type) { if (result != null) { // Result not unique; return null; @@ -251,33 +282,14 @@ return result; } - public List getExecutablePrimitiveTypeMirrors() { - List typeMirrors = new ArrayList<>(); - for (ExecutableTypeData executableType : executableTypes) { - typeMirrors.add(executableType.getType().getPrimitiveType()); - } - return typeMirrors; - } - - 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()]); - } - - public boolean hasUnexpectedExecutableTypes(ProcessorContext context) { - for (ExecutableTypeData type : getExecutableTypes()) { - if (type.hasUnexpectedValue(context)) { - return true; - } - } - return false; + return filteredFields.toArray(new NodeChildData[filteredFields.size()]); } public boolean needsRewrites(ProcessorContext context) { @@ -321,13 +333,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)); } @@ -373,8 +385,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; } @@ -382,12 +394,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() { @@ -412,12 +424,8 @@ return specializationListeners; } - public List getGuards() { - return guards; - } - public List getExecutableTypes() { - return executableTypes; + return getExecutableTypes(-1); } public List getShortCircuits() { @@ -437,11 +445,7 @@ this.specializationListeners = specializationListeners; } - void setGuards(List guards) { - this.guards = guards; - } - - void setExecutableTypes(List executableTypes) { + void setExecutableTypes(Map> executableTypes) { this.executableTypes = executableTypes; } diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java Sat Apr 20 12:23:29 2013 +0200 @@ -29,88 +29,27 @@ public class NodeFieldData extends MessageContainer { - public enum FieldKind { - CHILD, CHILDREN, 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 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java Sat Apr 20 12:23:29 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 { @@ -48,7 +48,7 @@ return spec; } - private static List nodeTypeMirrors(NodeData nodeData) { + protected List nodeTypeMirrors(NodeData nodeData) { Set typeMirrors = new LinkedHashSet<>(); for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) { @@ -66,11 +66,15 @@ @Override public boolean isParsable(ExecutableElement method) { - return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; + if (getAnnotationType() != null) { + return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; + } + + return true; } @SuppressWarnings("unused") - protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, String shortCircuitName) { + protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, boolean shortCircuitsEnabled, String shortCircuitName) { MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec()); if (getNode().supportsFrame()) { @@ -80,35 +84,36 @@ resolveAndAddImplicitThis(methodSpec, method); for (NodeFieldData field : getNode().getFields()) { - if (field.getKind() == FieldKind.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; - } - - methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class))); - methodSpec.addRequired(createValueParameterSpec(valueName, field.getNodeData())); - } else { - assert false; } } diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Sat Apr 20 12:23:29 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.*; @@ -73,7 +72,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(); @@ -114,87 +113,94 @@ 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); - - if (methodNodes == null && !Utils.isAssignable(type.asType(), context.getTruffleTypes().getNode())) { + AnnotationMirror methodNodes = Utils.findAnnotationMirror(processingEnv, templateType, NodeClass.class); + if (methodNodes == null && !Utils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) { return null; // not a node } - if (type.getModifiers().contains(Modifier.PRIVATE)) { - // TODO error message here!? - return null; // not visible, not a node + 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); } - TypeElement nodeType; - boolean needsSplit; - if (methodNodes != null) { - needsSplit = methodNodes != null; - nodeType = Utils.fromTypeMirror(Utils.getAnnotationValue(TypeMirror.class, methodNodes, "value")); - } else { - needsSplit = false; - nodeType = type; + 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))); - if (nodeData.hasErrors()) { - return nodeData; // error sync point - } + List nodeLookupTypes = findSuperClasses(new ArrayList(), Utils.fromTypeMirror(nodeType)); + Collections.reverse(nodeLookupTypes); + lookupTypes.addAll(nodeLookupTypes); - if (Utils.typeEquals(nodeType.asType(), type.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.FIELD) { + 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); - List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(type)); - nodeData.setExtensionElements(getExtensionParser().parseAll(nodeData, elements)); - if (nodeData.getExtensionElements() != null) { - elements.addAll(nodeData.getExtensionElements()); + NodeData node = parseNodeData(templateType, nodeType, elements, lookupTypes); + + if (node.hasErrors()) { + return node; // error sync point } - 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; } } @@ -299,23 +305,23 @@ } else if (node.needsRewrites(context)) { SpecializationData specialization = specializations.get(0); GenericParser parser = new GenericParser(context, node); - MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, null); + MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null); ExecutableTypeData anyGenericReturnType = node.findAnyGenericExecutableType(context); assert anyGenericReturnType != null; - ActualParameter returnType = new ActualParameter(specification.getReturnType(), anyGenericReturnType.getType().getPrimitiveType(), 0, false); + ActualParameter returnType = new ActualParameter(specification.getReturnType(), anyGenericReturnType.getType(), 0, false); List parameters = new ArrayList<>(); for (ActualParameter specializationParameter : specialization.getParameters()) { ParameterSpec parameterSpec = specification.findParameterSpec(specializationParameter.getSpecification().getName()); - NodeFieldData field = node.findField(parameterSpec.getName()); - TypeMirror actualType; - if (field == null || field.getKind() == FieldKind.FIELD) { - actualType = specializationParameter.getActualType(); + NodeChildData child = node.findChild(parameterSpec.getName()); + TypeData actualType; + 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().getPrimitiveType(); + actualType = paramType.getType(); } parameters.add(new ActualParameter(parameterSpec, actualType, specializationParameter.getIndex(), specializationParameter.isImplicit())); } @@ -328,18 +334,18 @@ if (genericSpecialization != null) { if (genericSpecialization.isUseSpecializationsForGeneric()) { for (ActualParameter parameter : genericSpecialization.getReturnTypeAndParameters()) { - if (Utils.isObject(parameter.getActualType())) { + if (Utils.isObject(parameter.getType())) { continue; } Set types = new HashSet<>(); for (SpecializationData specialization : specializations) { ActualParameter actualParameter = specialization.findParameter(parameter.getLocalName()); if (actualParameter != null) { - types.add(Utils.getQualifiedName(actualParameter.getActualType())); + types.add(Utils.getQualifiedName(actualParameter.getType())); } } if (types.size() > 1) { - genericSpecialization.replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, node.getTypeSystem().getGenericType())); + genericSpecialization.replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, node.getTypeSystem().getGenericTypeData())); } } } @@ -364,9 +370,13 @@ needsId.add(specialization); } } - List ids = calculateSpecializationIds(needsId); - for (int i = 0; i < ids.size(); i++) { - needsId.get(i).setId(ids.get(i)); + + // verify specialization parameter length + if (verifySpecializationParameters(node)) { + List ids = calculateSpecializationIds(needsId); + for (int i = 0; i < ids.size(); i++) { + needsId.get(i).setId(ids.get(i)); + } } } @@ -403,12 +413,12 @@ continue; } List paramIds = new LinkedList<>(); - paramIds.add(Utils.getTypeId(other.getReturnType().getActualType())); + 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.getActualType())); + paramIds.add(Utils.getTypeId(param.getType())); } assert lastSize == -1 || lastSize == paramIds.size(); if (lastSize != -1 && lastSize != paramIds.size()) { @@ -507,41 +517,27 @@ return signatures; } - private void verifyNode(NodeData nodeData) { - // verify specialization parameter length - verifySpecializationParameters(nodeData); - + private void verifyNode(NodeData nodeData, List elements) { // verify order is not ambiguous verifySpecializationOrder(nodeData); - verifyMissingAbstractMethods(nodeData); + verifyMissingAbstractMethods(nodeData, elements); assignShortCircuitsToSpecializations(nodeData); verifyConstructors(nodeData); -// if (!verifyNamingConvention(specializations, "do")) { -// return null; -// } -// -// if (!verifyNamesUnique(specializations)) { -// return null; -// } - verifyNamingConvention(nodeData.getShortCircuits(), "needs"); 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; } @@ -552,19 +548,26 @@ return nodeData; } - nodeData.setNodeType(nodeType.asType()); - nodeData.setTypeSystem(typeSystem); + boolean splitByMethodName = false; + AnnotationMirror nodeClass = findFirstAnnotation(lookupTypes, NodeClass.class); + if (nodeClass != null) { + splitByMethodName = Utils.getAnnotationValue(Boolean.class, nodeClass, "splitByMethodName"); + } - List executableTypes = filterExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)); - nodeData.setExecutableTypes(executableTypes); + 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); - nodeData.setFields(parseFields(elements, typeHierarchy)); + // parseChildren invokes cyclic parsing. + nodeData.setChildren(parseChildren(elements, lookupTypes)); return nodeData; } - private static void verifySpecializationParameters(NodeData nodeData) { + private static boolean verifySpecializationParameters(NodeData nodeData) { boolean valid = true; int args = -1; for (SpecializationData specializationData : nodeData.getSpecializations()) { @@ -585,16 +588,17 @@ specialization.addError("All specializations must have the same number of arguments."); } } + 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()) { @@ -604,6 +608,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)); @@ -618,8 +628,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(); @@ -638,38 +657,23 @@ nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type)); } - private static List filterExecutableTypes(List executableTypes) { - List filteredExecutableTypes = new ArrayList<>(); - for (ExecutableTypeData t1 : executableTypes) { - boolean add = true; - for (ExecutableTypeData t2 : executableTypes) { - if (t1 == t2) { - continue; - } - if (Utils.typeEquals(t1.getType().getPrimitiveType(), t2.getType().getPrimitiveType())) { - if (t1.isFinal() && !t2.isFinal()) { - add = false; - } - } + private static Map> groupExecutableTypes(List executableTypes) { + Map> groupedTypes = new HashMap<>(); + for (ExecutableTypeData type : executableTypes) { + int evaluatedCount = type.getEvaluatedCount(); + + List types = groupedTypes.get(evaluatedCount); + if (types == null) { + types = new ArrayList<>(); + groupedTypes.put(evaluatedCount, types); } - if (add) { - filteredExecutableTypes.add(t1); - } + types.add(type); } - Collections.sort(filteredExecutableTypes, new Comparator() { - - @Override - public int compare(ExecutableTypeData o1, ExecutableTypeData o2) { - int index1 = o1.getTypeSystem().findType(o1.getType()); - int index2 = o2.getTypeSystem().findType(o2.getType()); - if (index1 == -1 || index2 == -1) { - return 0; - } - return index1 - index2; - } - }); - return filteredExecutableTypes; + for (List types : groupedTypes.values()) { + Collections.sort(types); + } + return groupedTypes; } private AnnotationMirror findFirstAnnotation(List elements, Class annotation) { @@ -682,16 +686,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); @@ -700,136 +708,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.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); @@ -880,7 +866,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); @@ -917,14 +903,14 @@ 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.FIELD) { + NodeChildData field = node.findChild(parameter.getSpecification().getName()); + if (field == null) { continue; } ExecutableTypeData found = null; List executableElements = field.getNodeData().findGenericExecutableTypes(context); for (ExecutableTypeData executable : executableElements) { - if (executable.getType().equalsType(parameter.getActualTypeData(node.getTypeSystem()))) { + if (executable.getType().equalsType(parameter.getTypeSystemType())) { found = executable; break; } @@ -949,13 +935,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 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java Sat Apr 20 12:23:29 2013 +0200 @@ -62,7 +62,7 @@ for (ActualParameter param : getParameters()) { ActualParameter specializationParam = specialization.findParameter(param.getLocalName()); - if (!Utils.typeEquals(param.getActualType(), specializationParam.getActualType())) { + if (!Utils.typeEquals(param.getType(), specializationParam.getType())) { return false; } } diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitParser.java Sat Apr 20 12:23:29 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()); } } @@ -49,7 +49,7 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { String shortCircuitValue = Utils.getAnnotationValue(String.class, mirror, "value"); - return createDefaultMethodSpec(method, mirror, shortCircuitValue); + return createDefaultMethodSpec(method, mirror, true, shortCircuitValue); } @Override diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Sat Apr 20 12:23:29 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,11 +82,11 @@ return true; } for (ActualParameter parameter : getParameters()) { - NodeFieldData field = getNode().findField(parameter.getSpecification().getName()); - if (field == null || field.getKind() == FieldKind.FIELD) { + NodeChildData field = getNode().findChild(parameter.getSpecification().getName()); + if (field == null) { continue; } - ExecutableTypeData type = field.getNodeData().findExecutableType(parameter.getActualTypeData(field.getNodeData().getTypeSystem())); + ExecutableTypeData type = field.getNodeData().findExecutableType(parameter.getTypeSystemType()); if (type.hasUnexpectedValue(context)) { return true; } diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerParser.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerParser.java Sat Apr 20 12:23:29 2013 +0200 @@ -38,7 +38,7 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return createDefaultMethodSpec(method, mirror, null); + return createDefaultMethodSpec(method, mirror, true, null); } @Override diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java Sat Apr 20 12:23:29 2013 +0200 @@ -40,7 +40,7 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return createDefaultMethodSpec(method, mirror, null); + return createDefaultMethodSpec(method, mirror, true, null); } @Override diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java Sat Apr 20 12:23:29 2013 +0200 @@ -29,15 +29,17 @@ public class ActualParameter { private final ParameterSpec specification; - private final TypeMirror actualType; + private TypeData typeSystemType; private TemplateMethod method; private final String localName; private final int index; private final boolean implicit; + private final TypeMirror type; public ActualParameter(ParameterSpec specification, TypeMirror actualType, int index, boolean implicit) { this.specification = specification; - this.actualType = actualType; + this.type = actualType; + this.typeSystemType = null; this.index = index; this.implicit = implicit; @@ -49,7 +51,12 @@ this.localName = valueName; } - public ActualParameter(ActualParameter parameter, TypeMirror otherType) { + public ActualParameter(ParameterSpec specification, TypeData actualType, int index, boolean implicit) { + this(specification, actualType.getPrimitiveType(), index, implicit); + this.typeSystemType = actualType; + } + + public ActualParameter(ActualParameter parameter, TypeData otherType) { this(parameter.specification, otherType, parameter.index, parameter.implicit); } @@ -77,12 +84,12 @@ return method; } - public TypeMirror getActualType() { - return actualType; + public TypeMirror getType() { + return type; } - public TypeData getActualTypeData(TypeSystemData typeSystem) { - return typeSystem.findTypeData(actualType); + public TypeData getTypeSystemType() { + return typeSystemType; } public ActualParameter getPreviousParameter() { diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java Sat Apr 20 12:23:29 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 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java Sat Apr 20 12:23:29 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 { @@ -60,8 +60,9 @@ optional.add(spec); } - public void addRequired(ParameterSpec spec) { + public ParameterSpec addRequired(ParameterSpec spec) { required.add(spec); + return spec; } public List getImplicitRequiredTypes() { @@ -80,10 +81,6 @@ return optional; } - public void makeTypeDefinitions() { - - } - public List getAll() { List specs = new ArrayList<>(); specs.add(getReturnType()); @@ -154,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 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Sat Apr 20 12:23:29 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 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Sat Apr 20 12:23:29 2013 +0200 @@ -144,7 +144,9 @@ public List getReturnTypeAndParameters() { List allParameters = new ArrayList<>(getParameters().size() + 1); - allParameters.add(getReturnType()); + if (getReturnType() != null) { + allParameters.add(getReturnType()); + } allParameters.addAll(getParameters()); return Collections.unmodifiableList(allParameters); } @@ -186,13 +188,17 @@ return prev; } - public List getSignature(TypeSystemData typeSystem) { + public TypeData getReturnSignature() { + return getReturnType().getTypeSystemType(); + } + + public List getSignature() { List types = new ArrayList<>(); - for (ActualParameter parameter : getReturnTypeAndParameters()) { + for (ActualParameter parameter : getParameters()) { if (!parameter.getSpecification().isSignature()) { continue; } - TypeData typeData = parameter.getActualTypeData(typeSystem); + TypeData typeData = parameter.getTypeSystemType(); if (typeData != null) { types.add(typeData); } @@ -220,14 +226,27 @@ return compare; } + public List getParametersAfter(ActualParameter genericParameter) { + boolean found = false; + List foundParameters = new ArrayList<>(); + for (ActualParameter param : getParameters()) { + if (param.getLocalName().equals(genericParameter.getLocalName())) { + found = true; + } else if (found) { + foundParameters.add(param); + } + } + return foundParameters; + } + public int compareBySignature(TemplateMethod compareMethod) { TypeSystemData typeSystem = getTemplate().getTypeSystem(); if (typeSystem != compareMethod.getTemplate().getTypeSystem()) { throw new IllegalStateException("Cannot compare two methods with different type systems."); } - List signature1 = getSignature(typeSystem); - List signature2 = compareMethod.getSignature(typeSystem); + List signature1 = getSignature(); + List signature2 = compareMethod.getSignature(); if (signature1.size() != signature2.size()) { return signature2.size() - signature1.size(); } @@ -242,6 +261,12 @@ return 0; } } + if (result == 0) { + TypeData returnSignature1 = getReturnSignature(); + TypeData returnSignature2 = compareMethod.getReturnSignature(); + + result = compareActualParameter(typeSystem, returnSignature1, returnSignature2); + } return result; } diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java Sat Apr 20 12:23:29 2013 +0200 @@ -33,7 +33,8 @@ 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 { @@ -69,6 +70,10 @@ return context; } + public TypeSystemData getTypeSystem() { + return template.getTypeSystem(); + } + public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror); public abstract E create(TemplateMethod method); @@ -221,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; @@ -231,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; } @@ -243,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++; } } @@ -263,16 +268,22 @@ return parsedParams; } - private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template typeSystem, int index, boolean implicit) { + private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int index, boolean implicit) { TypeMirror resolvedType = mirror; if (hasError(resolvedType)) { - resolvedType = context.resolveNotYetCompiledType(mirror, typeSystem); + resolvedType = context.resolveNotYetCompiledType(mirror, originalTemplate); } if (!specification.matches(resolvedType)) { return null; } - return new ActualParameter(specification, resolvedType, index, implicit); + + TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType); + if (resolvedTypeData != null) { + return new ActualParameter(specification, resolvedTypeData, index, implicit); + } else { + return new ActualParameter(specification, resolvedType, index, implicit); + } } /* Helper class for parsing. */ diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java Sat Apr 20 12:23:29 2013 +0200 @@ -46,12 +46,12 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - MethodSpec spec = createDefaultMethodSpec(method, mirror, null); + MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null); spec.setVariableRequiredArguments(true); spec.getRequired().clear(); for (ActualParameter parameter : specialization.getRequiredParameters()) { - ParameterSpec paramSpec = new ParameterSpec(parameter.getLocalName(), parameter.getActualType(), getNode().getTypeSystem().getGenericType()); + ParameterSpec paramSpec = new ParameterSpec(parameter.getLocalName(), parameter.getType(), getNode().getTypeSystem().getGenericType()); paramSpec.setSignature(true); spec.addRequired(paramSpec); } @@ -82,7 +82,7 @@ if (specializationParameter == null) { newParameters.add(parameter); } else { - newParameters.add(new ActualParameter(specializationParameter.getSpecification(), parameter.getActualType(), specializationParameter.getIndex(), parameter.isImplicit())); + newParameters.add(new ActualParameter(specializationParameter.getSpecification(), parameter.getTypeSystemType(), specializationParameter.getIndex(), parameter.isImplicit())); } } guard.setParameters(newParameters); diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java Sat Apr 20 12:23:29 2013 +0200 @@ -51,7 +51,7 @@ public TypeCastData create(TemplateMethod method) { TypeData targetType = findTypeByMethodName(method, "as"); ActualParameter parameter = method.findParameter("valueValue"); - return new TypeCastData(method, parameter.getActualTypeData(getTypeSystem()), targetType); + return new TypeCastData(method, parameter.getTypeSystemType(), targetType); } @Override diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java Sat Apr 20 12:23:29 2013 +0200 @@ -53,7 +53,7 @@ assert checkedType != null; ActualParameter parameter = method.findParameter("valueValue"); assert parameter != null; - return new TypeCheckData(method, checkedType, parameter.getActualTypeData(getTypeSystem())); + return new TypeCheckData(method, checkedType, parameter.getTypeSystemType()); } @Override diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java Sat Apr 20 12:23:29 2013 +0200 @@ -110,4 +110,19 @@ return Utils.typeEquals(boxedType, actualTypeData.boxedType); } + public boolean needsCastTo(TypeData targetType) { + if (this.equals(targetType)) { + return false; + } else if (targetType.isGeneric()) { + return false; + } else if (targetType.isVoid()) { + return false; + } + return true; + } + + public boolean isPrimitive() { + return Utils.isPrimitive(getPrimitiveType()); + } + } diff -r 9b455ec15820 -r 9d29e5aa54d2 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 Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java Sat Apr 20 12:23:29 2013 +0200 @@ -34,10 +34,6 @@ super(context, typeSystem); } - public TypeSystemData getTypeSystem() { - return template; - } - @Override public final boolean isParsable(ExecutableElement method) { return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java Sat Apr 20 12:23:29 2013 +0200 @@ -74,7 +74,7 @@ if (expressions.size() >= 1) { StatementNode[] nodes = new StatementNode[expressions.size() + 1]; for (int i = 0; i < expressions.size(); i++) { - nodes[i] = PrintNodeFactory.create(expressions.get(i), printOutput); + nodes[i] = PrintNodeFactory.create(printOutput, expressions.get(i)); } nodes[expressions.size()] = new PrintLineNode(printOutput); return new BlockNode(nodes); diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -29,24 +29,8 @@ public abstract class ArithmeticNode extends BinaryNode { - public ArithmeticNode(TypedNode left, TypedNode right) { - super(left, right); - } - - protected ArithmeticNode(ArithmeticNode node) { - super(node); - } - public abstract static class AddNode extends ArithmeticNode { - public AddNode(TypedNode left, TypedNode right) { - super(left, right); - } - - protected AddNode(AddNode node) { - super(node); - } - @Specialization(rewriteOn = ArithmeticException.class) int doInt(int left, int right) { return ExactMath.addExact(left, right); @@ -70,14 +54,6 @@ public abstract static class SubNode extends ArithmeticNode { - public SubNode(TypedNode left, TypedNode right) { - super(left, right); - } - - protected SubNode(SubNode node) { - super(node); - } - @Specialization(rewriteOn = ArithmeticException.class) int sub(int left, int right) { return ExactMath.subtractExact(left, right); @@ -92,14 +68,6 @@ public abstract static class DivNode extends ArithmeticNode { - public DivNode(TypedNode left, TypedNode right) { - super(left, right); - } - - protected DivNode(DivNode node) { - super(node); - } - @Specialization(rewriteOn = ArithmeticException.class) int div(int left, int right) { return left / right; @@ -113,14 +81,6 @@ public abstract static class MulNode extends ArithmeticNode { - public MulNode(TypedNode left, TypedNode right) { - super(left, right); - } - - protected MulNode(MulNode node) { - super(node); - } - @Specialization(rewriteOn = ArithmeticException.class) int mul(int left, int right) { return ExactMath.multiplyExact(left, right); diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BinaryNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BinaryNode.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BinaryNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -24,20 +24,7 @@ import com.oracle.truffle.api.codegen.*; -@ExecuteChildren({"leftNode", "rightNode"}) +@NodeChildren({@NodeChild("leftNode"), @NodeChild("rightNode")}) public abstract class BinaryNode extends TypedNode { - @Child protected TypedNode leftNode; - - @Child protected TypedNode rightNode; - - public BinaryNode(TypedNode left, TypedNode right) { - this.leftNode = adoptChild(left); - this.rightNode = adoptChild(right); - } - - public BinaryNode(BinaryNode node) { - this(node.leftNode, node.rightNode); - } - } diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ConditionNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ConditionNode.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ConditionNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -28,4 +28,9 @@ public abstract boolean executeCondition(VirtualFrame frame); + @Override + public void executeVoid(VirtualFrame frame) { + executeCondition(frame); + } + } diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -25,23 +25,19 @@ import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.api.frame.*; -@ExecuteChildren("conditionNode") +@NodeChild(value = "conditionNode", type = ConditionNode.class) public abstract class IfNode extends StatementNode { - @Child protected ConditionNode conditionNode; - @Child private StatementNode thenPartNode; - @Child private StatementNode elsePartNode; - public IfNode(ConditionNode condition, StatementNode thenPart, StatementNode elsePart) { - this.conditionNode = adoptChild(condition); + public IfNode(StatementNode thenPart, StatementNode elsePart) { this.thenPartNode = adoptChild(thenPart); this.elsePartNode = adoptChild(elsePart); } protected IfNode(IfNode node) { - this(node.conditionNode, node.thenPartNode, node.elsePartNode); + this(node.thenPartNode, node.elsePartNode); } @Specialization diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LessThanNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LessThanNode.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LessThanNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -28,14 +28,6 @@ public abstract class LessThanNode extends BinaryNode { - public LessThanNode(TypedNode left, TypedNode right) { - super(left, right); - } - - public LessThanNode(LessThanNode node) { - this(node.leftNode, node.rightNode); - } - @Specialization public boolean doInteger(int left, int right) { return left < right; diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LogicalAndNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LogicalAndNode.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LogicalAndNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -27,14 +27,6 @@ @SuppressWarnings("unused") public abstract class LogicalAndNode extends BinaryNode { - public LogicalAndNode(TypedNode leftNode, TypedNode rightNode) { - super(leftNode, rightNode); - } - - public LogicalAndNode(LogicalAndNode node) { - this(node.leftNode, node.rightNode); - } - @ShortCircuit("rightNode") public boolean needsRightNode(boolean left) { return left; diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -26,19 +26,17 @@ import com.oracle.truffle.api.codegen.*; +@NodeChild(value = "expression", type = TypedNode.class) public abstract class PrintNode extends StatementNode { - @Child protected TypedNode expression; - private final PrintStream output; - public PrintNode(TypedNode expression, PrintStream output) { - this.expression = adoptChild(expression); + public PrintNode(PrintStream output) { this.output = output; } public PrintNode(PrintNode node) { - this(node.expression, node.output); + this(node.output); } @Specialization diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TernaryNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TernaryNode.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TernaryNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -27,25 +27,9 @@ import com.oracle.truffle.api.codegen.*; @SuppressWarnings("unused") -@ExecuteChildren({"conditionNode", "ifPartNode", "elsePartNode"}) +@NodeChildren({@NodeChild(value = "conditionNode", type = ConditionNode.class), @NodeChild("ifPartNode"), @NodeChild("elsePartNode")}) public abstract class TernaryNode extends TypedNode { - @Child protected ConditionNode conditionNode; - - @Child protected TypedNode ifPartNode; - - @Child protected TypedNode elsePartNode; - - public TernaryNode(ConditionNode condition, TypedNode ifPart, TypedNode elsePart) { - this.conditionNode = adoptChild(condition); - this.ifPartNode = adoptChild(ifPart); - this.elsePartNode = adoptChild(elsePart); - } - - public TernaryNode(TernaryNode condition) { - this(condition.conditionNode, condition.ifPartNode, condition.elsePartNode); - } - @ShortCircuit("ifPartNode") public boolean needsIfPart(boolean condition) { return condition; diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TypedNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TypedNode.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TypedNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -26,6 +26,7 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.*; public abstract class TypedNode extends ConditionNode { @@ -38,18 +39,46 @@ } } - public abstract boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException; + public abstract Object executeGeneric(VirtualFrame frame); - public abstract int executeInteger(VirtualFrame frame) throws UnexpectedResultException; + public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException { + return SLTypesGen.SLTYPES.expectBoolean(executeGeneric(frame)); + } + + public int executeInteger(VirtualFrame frame) throws UnexpectedResultException { + return SLTypesGen.SLTYPES.expectInteger(executeGeneric(frame)); + } - public abstract BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException; + public BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException { + return SLTypesGen.SLTYPES.expectBigInteger(executeGeneric(frame)); + } - public abstract String executeString(VirtualFrame frame) throws UnexpectedResultException; + public String executeString(VirtualFrame frame) throws UnexpectedResultException { + return SLTypesGen.SLTYPES.expectString(executeGeneric(frame)); + } - public abstract Object executeGeneric(VirtualFrame frame); + @Override + public void executeVoid(VirtualFrame frame) { + executeGeneric(frame); + } public boolean isString(Object a, Object b) { return a instanceof String || b instanceof String; } + @SuppressWarnings("unused") + public Object executeEvaluated(VirtualFrame frame, Object val1) { + return executeGeneric(frame); + } + + @SuppressWarnings("unused") + public Object executeEvaluated(VirtualFrame frame, Object val1, Object val2) { + return executeEvaluated(frame, val1); + } + + @SuppressWarnings("unused") + public Object executeEvaluated(VirtualFrame frame, Object val1, Object val2, Object val3) { + return executeEvaluated(frame, val1, val2); + } + } diff -r 9b455ec15820 -r 9d29e5aa54d2 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java Fri Apr 19 16:41:54 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -27,17 +27,15 @@ import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.api.frame.*; +@NodeChild(value = "rightNode", type = TypedNode.class) public abstract class WriteLocalNode extends FrameSlotNode { - @Child protected TypedNode rightNode; - - public WriteLocalNode(FrameSlot slot, TypedNode right) { + public WriteLocalNode(FrameSlot slot) { super(slot); - this.rightNode = adoptChild(right); } public WriteLocalNode(WriteLocalNode node) { - this(node.slot, node.rightNode); + this(node.slot); } @Specialization