# HG changeset patch # User Christian Humer # Date 1389117184 -3600 # Node ID 856c2c294f84436a645606d7035be3c072ef6ddc # Parent 5a0c694ef735053dc64ecbbe6bf04f6766b3ac87# Parent 56452e07874f936e2e4292e63d3c5cafd81542c1 Merge. diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BoxedString.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BoxedString.java Tue Jan 07 18:53:04 2014 +0100 @@ -0,0 +1,41 @@ +/* + * 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.api.dsl.test; + +public class BoxedString { + + private final String delegate; + + public BoxedString(String delegate) { + this.delegate = delegate; + } + + public String getDelegate() { + return delegate; + } + + @Override + public String toString() { + return getDelegate(); + } +} diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java Tue Jan 07 18:53:04 2014 +0100 @@ -38,8 +38,6 @@ import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve1Factory; import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve2Factory; import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve3Factory; -import com.oracle.truffle.api.dsl.test.NodeContainerTest.Str; -import com.oracle.truffle.api.dsl.test.NodeContainerTest.StrBase; import com.oracle.truffle.api.dsl.test.TypeSystemTest.Abstract; import com.oracle.truffle.api.dsl.test.TypeSystemTest.BExtendsAbstract; import com.oracle.truffle.api.dsl.test.TypeSystemTest.CExtendsAbstract; @@ -124,18 +122,18 @@ public void testGuardWithBaseClass() { TestRootNode root = createRoot(GuardWithBaseClassFactory.getInstance()); - assertEquals(42, executeWith(root, new Str("42"))); + assertEquals(42, executeWith(root, new BExtendsAbstract())); } @NodeChild("expression") public abstract static class GuardWithBaseClass extends ValueNode { - boolean baseGuard(StrBase base) { + boolean baseGuard(Abstract base) { return true; } @Specialization(guards = "baseGuard") - int doSpecialized(Str value0) { + int doSpecialized(BExtendsAbstract value0) { return 42; } } @@ -227,7 +225,7 @@ @Test public void testGuardResolve2() { TestRootNode root = createRoot(TestGuardResolve2Factory.getInstance()); - assertEquals(42, executeWith(root, new Str(""))); + assertEquals(42, executeWith(root, new BExtendsAbstract())); } @NodeChild("expression") @@ -237,12 +235,12 @@ return false; } - boolean guard(StrBase primitive) { + boolean guard(Abstract primitive) { return true; } @Specialization(guards = "guard") - int doSpecialized(Str value0) { + int doSpecialized(BExtendsAbstract value0) { return 42; } } @@ -251,7 +249,7 @@ public void testGuardResolve3() { TestRootNode root = createRoot(TestGuardResolve3Factory.getInstance()); - assertEquals(42, executeWith(root, new Str(""))); + assertEquals(42, executeWith(root, new BExtendsAbstract())); } @NodeChild("expression") @@ -261,16 +259,16 @@ return false; } - boolean guard(StrBase primitive) { + boolean guard(Abstract primitive) { return false; } - boolean guard(Str primitive) { + boolean guard(BExtendsAbstract primitive) { return true; } @Specialization(guards = "guard") - int doSpecialized(Str value0) { + int doSpecialized(BExtendsAbstract value0) { return 42; } } @@ -278,12 +276,12 @@ @NodeChild("expression") public abstract static class TestGuardResolve4 extends ValueNode { - boolean guard(StrBase primitive) { + boolean guard(Abstract primitive) { return false; } @Specialization(guards = "guard") - int doSpecialized(Str value0) { + int doSpecialized(BExtendsAbstract value0) { return 42; } } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java Tue Jan 07 18:53:04 2014 +0100 @@ -28,14 +28,13 @@ import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast0NodeFactory; import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast1NodeFactory; import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast2NodeFactory; -import com.oracle.truffle.api.dsl.test.NodeContainerTest.Str; import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; import com.oracle.truffle.api.frame.*; public class ImplicitCastTest { - @TypeSystem({int.class, boolean.class, String.class, Str.class}) + @TypeSystem({int.class, boolean.class, String.class}) static class ImplicitCast0Types { @ImplicitCast diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeContainerTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeContainerTest.java Tue Jan 07 14:41:52 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,179 +0,0 @@ -/* - * 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.dsl.test; - -import static com.oracle.truffle.api.dsl.test.TestHelper.*; -import static org.junit.Assert.*; - -import org.junit.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.test.NodeContainerTestFactory.StrFactory.StrAccessContextFactory; -import com.oracle.truffle.api.dsl.test.NodeContainerTestFactory.StrFactory.StrConcatFactory; -import com.oracle.truffle.api.dsl.test.NodeContainerTestFactory.StrFactory.StrLengthFactory; -import com.oracle.truffle.api.dsl.test.NodeContainerTestFactory.StrFactory.StrSubstrFactory; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; - -public class NodeContainerTest { - - @Test - public void testConcat() { - TestRootNode node = createRoot(StrConcatFactory.getInstance(), new Context()); - Str str1 = new Str("42"); - Str str2 = new Str(" is the number."); - assertEquals(str1.concat(str2), executeWith(node, str1, str2)); - } - - @Test(expected = UnsupportedOperationException.class) - public void testConcatUnsupported() { - TestRootNode node = createRoot(StrConcatFactory.getInstance(), new Context()); - executeWith(node, 42, new Str(" is the number.")); - } - - @Test - public void testSubstrSpecialized() { - TestRootNode node = createRoot(StrSubstrFactory.getInstance(), new Context()); - Str str = new Str("test 42"); - - assertEquals(str.substr(5, 7), executeWith(node, str, 5, 7)); - } - - @Test - public void testSubstrGeneric() { - TestRootNode node = createRoot(StrSubstrFactory.getInstance(), new Context()); - Str str = new Str("test 42"); - - assertEquals(Str.substr(str, "5", "7"), executeWith(node, str, "5", "7")); - } - - @Test(expected = UnsupportedOperationException.class) - public void testSubstrUnsupported() { - TestRootNode node = createRoot(StrSubstrFactory.getInstance(), new Context()); - executeWith(node, new Object(), "5", "7"); - } - - @Test - public void testLength() { - TestRootNode node = createRoot(StrLengthFactory.getInstance(), new Context()); - Str testStr = new Str("test 42"); - assertEquals(testStr.length(), executeWith(node, testStr)); - } - - @Test(expected = UnsupportedOperationException.class) - public void testLengthUnsupported() { - TestRootNode node = createRoot(StrLengthFactory.getInstance(), new Context()); - executeWith(node, new Object()); - } - - @Test - public void testAccessContext() { - Context context = new Context(); - TestRootNode node = createRoot(StrAccessContextFactory.getInstance(), context); - // accessible by node - assertSame(context, node.getNode().getContext()); - // accessible by execution - assertSame(context, executeWith(node)); - } - - static class StrBase { - - } - - @NodeContainer(BuiltinNode.class) - static class Str extends StrBase { - - private final String internal; - - public Str(String internal) { - this.internal = internal; - } - - @Specialization - Str concat(Str s1) { - return new Str(internal + s1.internal); - } - - @Specialization - Str substr(int beginIndex, int endIndex) { - return new Str(internal.substring(beginIndex, endIndex)); - } - - @Generic - static Str substr(Object thisValue, Object beginIndex, Object endIndex) { - if (!(thisValue instanceof Str)) { - throw new UnsupportedOperationException(); - } - return ((Str) thisValue).substr(convertInt(beginIndex), convertInt(endIndex)); - } - - @Specialization - int length() { - return internal.length(); - } - - @Specialization - static Object accessContext(Context context) { - return context; - } - - static int convertInt(Object value) { - if (value instanceof Number) { - return ((Number) value).intValue(); - } else if (value instanceof String) { - return Integer.parseInt((String) value); - } - throw new RuntimeException("Invalid datatype"); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Str) { - return internal.equals(((Str) obj).internal); - } - return super.equals(obj); - } - - @Override - public String toString() { - return internal; - } - - @Override - public int hashCode() { - return internal.hashCode(); - } - } - - @NodeChild(value = "children", type = ValueNode[].class) - @NodeField(name = "context", type = Context.class) - abstract static class BuiltinNode extends ValueNode { - - public abstract Context getContext(); - } - - static class Context { - - } - -} diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java Tue Jan 07 18:53:04 2014 +0100 @@ -28,8 +28,13 @@ import org.junit.*; import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.*; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.TestContainerFactory.TestContainerContainerFieldFactory; +import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldNoGetterTestNodeFactory; +import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldTestNodeFactory; +import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.MultipleFieldsTestNodeFactory; +import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.ObjectContainerNodeFactory; +import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.RewriteTestNodeFactory; +import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.StringFieldTestNodeFactory; +import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.TestContainerFactory; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; public class NodeFieldTest { @@ -125,7 +130,7 @@ @Test public void testStringContainer() { - assertEquals(42, createCallTarget(TestContainerContainerFieldFactory.create(42, "42")).call()); + assertEquals(42, createCallTarget(TestContainerFactory.create("42")).call()); } @NodeField(name = "field", type = int.class) @@ -135,13 +140,12 @@ } - @NodeContainer(IntContainerNode.class) @NodeField(name = "anotherField", type = String.class) - abstract static class TestContainer { + abstract static class TestContainer extends ValueNode { @Specialization - static int containerField(int field, String anotherField) { - return anotherField.equals("42") ? field : -1; + int containerField(String field) { + return field.equals("42") ? 42 : -1; } } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java Tue Jan 07 18:53:04 2014 +0100 @@ -0,0 +1,144 @@ +/* + * 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.dsl.test; + +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.DoubleChildNodeFactory; +import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.SingleChildNodeFactory; +import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.VarArgsNodeFactory; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestArguments; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; + +public class ShortCircuitTest { + + @Test + public void testSingleChild1() { + ArgumentNode arg0 = new ArgumentNode(0); + CallTarget callTarget = TestHelper.createCallTarget(SingleChildNodeFactory.create(arg0)); + SingleChildNode.needsChild = true; + assertEquals(42, callTarget.call(new TestArguments(42))); + assertEquals(1, arg0.getInvocationCount()); + } + + @Test + public void testSingleChild2() { + ArgumentNode arg0 = new ArgumentNode(0); + CallTarget callTarget = TestHelper.createCallTarget(SingleChildNodeFactory.create(arg0)); + SingleChildNode.needsChild = false; + assertEquals(0, callTarget.call(new TestArguments(42))); + assertEquals(0, arg0.getInvocationCount()); + } + + @NodeChild("child0") + abstract static class SingleChildNode extends ValueNode { + + static boolean needsChild; + + @ShortCircuit("child0") + boolean needsChild0() { + return needsChild; + } + + @Specialization + int doIt(boolean hasChild0, int child0) { + assert hasChild0 == needsChild0(); + return child0; + } + + } + + @Test + public void testDoubleChild1() { + ArgumentNode arg0 = new ArgumentNode(0); + ArgumentNode arg1 = new ArgumentNode(1); + CallTarget callTarget = TestHelper.createCallTarget(DoubleChildNodeFactory.create(arg0, arg1)); + assertEquals(42, callTarget.call(new TestArguments(41, 42))); + assertEquals(1, arg1.getInvocationCount()); + } + + @Test + public void testDoubleChild2() { + ArgumentNode arg0 = new ArgumentNode(0); + ArgumentNode arg1 = new ArgumentNode(1); + CallTarget callTarget = TestHelper.createCallTarget(DoubleChildNodeFactory.create(arg0, arg1)); + assertEquals(0, callTarget.call(new TestArguments(42, 42))); + assertEquals(0, arg1.getInvocationCount()); + } + + @NodeChildren({@NodeChild("child0"), @NodeChild("child1")}) + @SuppressWarnings("unused") + abstract static class DoubleChildNode extends ValueNode { + + @ShortCircuit("child1") + boolean needsChild1(Object leftValue) { + return leftValue.equals(41); + } + + @Specialization + int doIt(int child0, boolean hasChild1, int child1) { + return child1; + } + + } + + @Test + public void testVarArgs1() { + ArgumentNode arg0 = new ArgumentNode(0); + ArgumentNode arg1 = new ArgumentNode(1); + CallTarget callTarget = TestHelper.createCallTarget(VarArgsNodeFactory.create(new ValueNode[]{arg0, arg1})); + assertEquals(42, callTarget.call(new TestArguments(41, 42))); + assertEquals(1, arg1.getInvocationCount()); + } + + @Test + public void testVarArgs2() { + ArgumentNode arg0 = new ArgumentNode(0); + ArgumentNode arg1 = new ArgumentNode(1); + CallTarget callTarget = TestHelper.createCallTarget(VarArgsNodeFactory.create(new ValueNode[]{arg0, arg1})); + assertEquals(0, callTarget.call(new TestArguments(42, 42))); + assertEquals(0, arg1.getInvocationCount()); + } + + @NodeChild(value = "children", type = ValueNode[].class) + abstract static class VarArgsNode extends ValueNode { + + @ShortCircuit("children[1]") + boolean needsChild1(Object leftValue) { + return leftValue.equals(41); + } + + @Specialization + @SuppressWarnings("unused") + int doIt(int child0, boolean hasChild1, int child1) { + return child1; + } + + } + +} diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Tue Jan 07 18:53:04 2014 +0100 @@ -28,7 +28,6 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.test.NodeContainerTest.BuiltinNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ChildrenNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestArguments; @@ -52,7 +51,7 @@ ArgumentNode[] argumentNodes = arguments(factory.getExecutionSignature().size()); List argumentList = new ArrayList<>(); - if (ChildrenNode.class.isAssignableFrom(factory.getNodeClass()) || BuiltinNode.class.isAssignableFrom(factory.getNodeClass())) { + if (ChildrenNode.class.isAssignableFrom(factory.getNodeClass())) { argumentList.add(argumentNodes); } else { argumentList.addAll(Arrays.asList(argumentNodes)); diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java Tue Jan 07 18:53:04 2014 +0100 @@ -24,13 +24,12 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.test.NodeContainerTest.Str; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; public class TypeSystemTest { - @TypeSystem({int.class, boolean.class, String.class, Str.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class, Abstract.class, Object[].class}) + @TypeSystem({int.class, boolean.class, String.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class, Abstract.class, Object[].class}) static class SimpleTypes { static int intCheck; @@ -48,11 +47,6 @@ return (int) value; } - @ImplicitCast - Str castStr(String strvalue) { - return new Str(strvalue); - } - } @TypeSystemReference(SimpleTypes.class) @@ -66,10 +60,6 @@ return SimpleTypesGen.SIMPLETYPES.expectInteger(execute(frame)); } - public Str executeStr(VirtualFrame frame) throws UnexpectedResultException { - return SimpleTypesGen.SIMPLETYPES.expectStr(execute(frame)); - } - public String executeString(VirtualFrame frame) throws UnexpectedResultException { return SimpleTypesGen.SIMPLETYPES.expectString(execute(frame)); } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/package-info.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/package-info.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/package-info.java Tue Jan 07 18:53:04 2014 +0100 @@ -41,7 +41,6 @@ * *
    *
  • What do I need to get started? {@link com.oracle.truffle.api.dsl.test.TypeSystemTest}
  • - *
  • How would you generate function nodes for runtime objects? {@link com.oracle.truffle.api.dsl.test.NodeContainerTest}
  • *
*

* diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeContainer.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeContainer.java Tue Jan 07 14:41:52 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.dsl; - -import java.lang.annotation.*; - -import com.oracle.truffle.api.nodes.*; - -/** - * A node container can be used to enable Truffle-DSL in classes which do not extend {@link Node}. - * Compared to normal {@link Node} implementation the nodes are not identified by a class but by - * their method name. There are cases were method signatures are matching exactly but should be in - * the same {@link Node}. In this case use {@link NodeId} to disambiguate such cases. - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.TYPE}) -public @interface NodeContainer { - - /** The node class to use as base class for {@link Node} definitions grouped by method names. */ - Class value(); - -} diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeId.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeId.java Tue Jan 07 14:41:52 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.dsl; - -import java.lang.annotation.*; - -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD, ElementType.TYPE}) -public @interface NodeId { - - String value(); - -} diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/SpecializationListener.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/SpecializationListener.java Tue Jan 07 14:41:52 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.dsl; - -import java.lang.annotation.*; - -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD}) -public @interface SpecializationListener { -} diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java Tue Jan 07 18:53:04 2014 +0100 @@ -46,17 +46,21 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { List childNames = Utils.getAnnotationValueList(String.class, mirror, "value"); - TypeMirror baseType = getContext().getTruffleTypes().getNode(); + NodeChildData foundChild = null; for (String childName : childNames) { - NodeChildData child = getNode().findChild(childName); - if (child != null) { - baseType = child.getOriginalType(); + foundChild = getNode().findChild(childName); + if (foundChild != null) { break; } } + TypeMirror baseType = getContext().getTruffleTypes().getNode(); + if (foundChild != null) { + baseType = foundChild.getOriginalType(); + } + MethodSpec spec = new MethodSpec(new InheritsParameterSpec(getContext(), "child", baseType)); addDefaultFieldMethodSpec(spec); - spec.addRequired(new ParameterSpec("castedChild", baseType)).setSignature(true); + spec.addRequired(new ParameterSpec("castedChild", baseType)); return spec; } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java Tue Jan 07 18:53:04 2014 +0100 @@ -29,7 +29,6 @@ import javax.lang.model.type.*; import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.node.NodeChildData.*; import com.oracle.truffle.dsl.processor.template.*; import com.oracle.truffle.dsl.processor.typesystem.*; @@ -52,13 +51,11 @@ for (ParameterSpec originalSpec : requiredSpecs) { spec.addRequired(new ParameterSpec(originalSpec, allowedTypes)); } - - spec.setVariableRequiredArguments(true); - ParameterSpec other = new ParameterSpec("other", allowedTypes); - other.setCardinality(Cardinality.MANY); - other.setSignature(true); - other.setIndexed(true); - spec.addRequired(other); + spec.setIgnoreAdditionalSpecifications(true); + spec.setIgnoreAdditionalParameters(true); + spec.setVariableRequiredParameters(true); + // varargs + spec.addRequired(new ParameterSpec("other", allowedTypes)); return spec; } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java Tue Jan 07 18:53:04 2014 +0100 @@ -30,6 +30,7 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.node.SpecializationData.SpecializationKind; import com.oracle.truffle.dsl.processor.template.*; public class GenericParser extends NodeMethodParser { @@ -44,26 +45,20 @@ } @Override - protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, int evaluatedCount) { - List execTypes = nodeData.findGenericExecutableTypes(getContext(), evaluatedCount); + protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) { + List execTypes = execution.getChild().getNodeData().findGenericExecutableTypes(getContext(), execution.getChild().getExecuteWith().size()); List types = new ArrayList<>(); for (ExecutableTypeData type : execTypes) { types.add(type.getType().getPrimitiveType()); } - ParameterSpec spec = new ParameterSpec(valueName, types); - spec.setSignature(true); + ParameterSpec spec = new ParameterSpec(execution.getName(), types); + spec.setExecution(execution); return spec; } @Override - protected ParameterSpec createReturnParameterSpec() { - return super.createValueParameterSpec("returnValue", getNode(), 0); - } - - @Override public SpecializationData create(TemplateMethod method, boolean invalid) { - SpecializationData data = new SpecializationData(method, true, false, false); - return data; + return new SpecializationData(getNode(), method, SpecializationKind.GENERIC); } @Override diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java Tue Jan 07 18:53:04 2014 +0100 @@ -45,29 +45,20 @@ } } - public enum ExecutionKind { - DEFAULT, SHORT_CIRCUIT - } - - private final NodeData parent; + private NodeData parentNode; private final Element sourceElement; private final AnnotationMirror sourceAnnotationMirror; - private final String name; private final TypeMirror type; private final TypeMirror originalType; private final Element accessElement; - private final Cardinality cardinality; - private final ExecutionKind executionKind; private List executeWith = Collections.emptyList(); - private NodeData nodeData; + private NodeData childNode; - public NodeChildData(NodeData parent, Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, - Cardinality cardinality, ExecutionKind executionKind) { - this.parent = parent; + public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality) { this.sourceElement = sourceElement; this.sourceAnnotationMirror = sourceMirror; this.name = name; @@ -75,7 +66,10 @@ this.originalType = originalNodeType; this.accessElement = accessElement; this.cardinality = cardinality; - this.executionKind = executionKind; + } + + void setParentNode(NodeData parentNode) { + this.parentNode = parentNode; } public List getExecuteWith() { @@ -87,23 +81,17 @@ } public boolean needsImplicitCast(ProcessorContext context) { - if (!parent.needsRewrites(context)) { + if (!parentNode.needsRewrites(context)) { return false; } boolean used = false; - SpecializationData generic = parent.getGenericSpecialization(); - for (ActualParameter param : generic.getParameters()) { - if (!param.getSpecification().isSignature()) { - continue; - } - NodeChildData child = parent.findChild(param.getSpecification().getName()); - if (child == this) { + for (NodeExecutionData execution : parentNode.getChildExecutions()) { + if (execution.getChild() == this) { used = true; break; } } - if (!used) { return false; } @@ -112,7 +100,7 @@ } public ExecutableTypeData findExecutableType(ProcessorContext context, TypeData targetType) { - ExecutableTypeData executableType = nodeData.findExecutableType(targetType, getExecuteWith().size()); + ExecutableTypeData executableType = childNode.findExecutableType(targetType, getExecuteWith().size()); if (executableType == null) { executableType = findAnyGenericExecutableType(context); } @@ -120,15 +108,15 @@ } public List findGenericExecutableTypes(ProcessorContext context) { - return nodeData.findGenericExecutableTypes(context, getExecuteWith().size()); + return childNode.findGenericExecutableTypes(context, getExecuteWith().size()); } public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) { - return nodeData.findAnyGenericExecutableType(context, getExecuteWith().size()); + return childNode.findAnyGenericExecutableType(context, getExecuteWith().size()); } public List findExecutableTypes() { - return nodeData.getExecutableTypes(getExecuteWith().size()); + return childNode.getExecutableTypes(getExecuteWith().size()); } public TypeMirror getOriginalType() { @@ -145,12 +133,8 @@ return sourceAnnotationMirror; } - public boolean isShortCircuit() { - return executionKind == ExecutionKind.SHORT_CIRCUIT; - } - void setNode(NodeData nodeData) { - this.nodeData = nodeData; + this.childNode = nodeData; if (nodeData != null) { getMessages().addAll(nodeData.collectMessages()); } @@ -168,12 +152,8 @@ return cardinality; } - public ExecutionKind getExecutionKind() { - return executionKind; - } - public NodeData getNodeData() { - return nodeData; + return childNode; } public String getName() { @@ -182,7 +162,7 @@ @Override public String toString() { - return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", execution=" + executionKind + ", node=" + getNodeData() + "]"; + return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", node=" + getNodeData() + "]"; } } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Tue Jan 07 18:53:04 2014 +0100 @@ -37,7 +37,6 @@ import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.ast.*; import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; -import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind; import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard; import com.oracle.truffle.dsl.processor.template.*; import com.oracle.truffle.dsl.processor.typesystem.*; @@ -48,6 +47,7 @@ private static final String EXECUTE_GENERIC_NAME = "executeGeneric0"; private static final String EXECUTE_SPECIALIZE_NAME = "executeAndSpecialize0"; + private static final String EXECUTE_POLYMORPHIC_NAME = "executePolymorphic0"; private static final String UPDATE_TYPES_NAME = "updateTypes"; @@ -71,16 +71,8 @@ return name; } - private static String nodePolymorphicClassName(NodeData node, SpecializationData specialization) { - String nodeid = resolveNodeId(node); - - String name = Utils.firstLetterUpperCase(nodeid); - if (specialization == node.getGenericPolymorphicSpecialization()) { - name += "PolymorphicNode"; - } else { - name += "Polymorphic" + polymorphicIndex(node, specialization) + "Node"; - } - return name; + private static String nodePolymorphicClassName(NodeData node) { + return Utils.firstLetterUpperCase(resolveNodeId(node)) + "PolymorphicNode"; } private static String resolveNodeId(NodeData node) { @@ -111,30 +103,6 @@ return valueName(parameter) + "Cast"; } - private static String executeCachedName(SpecializationData polymorphic) { - NodeData node = polymorphic.getNode(); - boolean generic = polymorphic == node.getGenericPolymorphicSpecialization(); - - if (generic) { - return "executeCachedGeneric0"; - } else { - return "executeCached" + polymorphicIndex(node, polymorphic); - } - } - - private static int polymorphicIndex(NodeData node, SpecializationData polymorphic) { - int index = 0; - for (SpecializationData specialization : node.getPolymorphicSpecializations()) { - if (specialization == polymorphic) { - break; - } - if (specialization != node.getGenericPolymorphicSpecialization()) { - index++; - } - } - return index; - } - private void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean evaluated) { if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); @@ -440,11 +408,9 @@ getElement().getEnclosedElements().clear(); Map> childTypes = new LinkedHashMap<>(); - 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()); - } + for (NodeData nodeChild : node.getEnclosingNodes()) { + NodeCodeGenerator generator = new NodeCodeGenerator(getContext()); + childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements()); } if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) { @@ -526,15 +492,18 @@ createFactoryMethods(node, clazz, createVisibility); - if (node.isPolymorphic()) { - PolymorphicNodeFactory generic = new PolymorphicNodeFactory(getContext(), generatedNode); - add(generic, node.getGenericPolymorphicSpecialization()); - polymorphicNode = generic.getElement(); - } for (SpecializationData specialization : node.getSpecializations()) { if (!specialization.isReachable()) { continue; } + + if (specialization.isPolymorphic() && node.isPolymorphic()) { + PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(getContext(), generatedNode); + add(polymorphicFactory, specialization); + polymorphicNode = polymorphicFactory.getElement(); + continue; + } + add(new SpecializedNodeFactory(context, generatedNode), specialization); } @@ -573,7 +542,7 @@ } List children = node.getNodeDeclaringChildren(); - if (node.getParent() == null && children.size() > 0) { + if (node.getDeclaringNode() == null && children.size() > 0) { clazz.add(createGetFactories(node)); } @@ -632,21 +601,9 @@ List signatureTypes = new ArrayList<>(); assert !node.getSpecializations().isEmpty(); SpecializationData data = node.getSpecializations().get(0); - for (ActualParameter parameter : data.getParameters()) { - ParameterSpec spec = parameter.getSpecification(); - NodeChildData field = node.findChild(spec.getName()); - if (field == null) { - continue; - } - - TypeMirror type; - if (field.getCardinality() == Cardinality.MANY && field.getNodeType().getKind() == TypeKind.ARRAY) { - type = ((ArrayType) field.getNodeType()).getComponentType(); - } else { - type = field.getNodeType(); - } - - signatureTypes.add(type); + + for (ActualParameter parameter : data.getSignatureParameters()) { + signatureTypes.add(parameter.getSpecification().getExecution().getNodeType()); } builder.startReturn().tree(createAsList(builder, signatureTypes, classType)).end(); @@ -768,7 +725,7 @@ } private String instanceVarName(NodeData node) { - if (node.getParent() != null) { + if (node.getDeclaringNode() != null) { return Utils.firstLetterLowerCase(factoryClassName(node)) + "Instance"; } else { return "instance"; @@ -821,9 +778,9 @@ builder.startGroup(); NodeData childNode = child; List factories = new ArrayList<>(); - while (childNode.getParent() != null) { + while (childNode.getDeclaringNode() != null) { factories.add(childNode); - childNode = childNode.getParent(); + childNode = childNode.getDeclaringNode(); } Collections.reverse(factories); for (NodeData nodeData : factories) { @@ -963,7 +920,7 @@ builder.statement("this.next0 = adoptChild(next0)"); clazz.add(setter); - CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getGenericPolymorphicSpecialization()); + CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization()); clazz.add(genericCachedExecute); getElement().add(createUpdateTypes(clazz.asType())); @@ -1014,16 +971,13 @@ CodeTreeBuilder oldBuilder = builder.create(); CodeTreeBuilder resetBuilder = builder.create(); - for (ActualParameter param : getModel().getParameters()) { - if (!param.getSpecification().isSignature()) { - continue; - } - NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); + for (ActualParameter param : getModel().getSignatureParameters()) { + NodeChildData child = param.getSpecification().getExecution().getChild(); CodeTreeBuilder access = builder.create(); access.string("this.").string(child.getName()); if (child.getCardinality().isMany()) { - access.string("[").string(String.valueOf(param.getSpecificationIndex())).string("]"); + access.string("[").string(String.valueOf(param.getSpecificationVarArgsIndex())).string("]"); } String oldName = "old" + Utils.firstLetterUpperCase(param.getLocalName()); @@ -1117,11 +1071,7 @@ builder.startStatement().startCall("builder", "append").doubleQuote(" (").end().end(); String sep = null; - for (ActualParameter parameter : node.getGenericSpecialization().getParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - + for (ActualParameter parameter : node.getGenericSpecialization().getSignatureParameters()) { builder.startStatement(); builder.string("builder"); if (sep != null) { @@ -1164,8 +1114,7 @@ } private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) { - String name = executeCachedName(polymorph); - CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), name); + CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_POLYMORPHIC_NAME); addInternalValueParameters(cachedExecute, polymorph, true, true); ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0); @@ -1210,15 +1159,6 @@ } } - for (VariableElement var : type.getFields()) { - NodeChildData child = node.findChild(var.getSimpleName().toString()); - if (child != null) { - method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName())); - } else { - method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString())); - } - } - if (superConstructor != null) { builder.startStatement().startSuperCall(); for (VariableElement param : superConstructor.getParameters()) { @@ -1228,11 +1168,18 @@ } for (VariableElement var : type.getFields()) { + NodeExecutionData execution = node.findExecution(var.getSimpleName().toString()); + NodeChildData child = execution != null ? execution.getChild() : null; + + if (execution != null) { + method.getParameters().add(new CodeVariableElement(execution.getNodeType(), execution.getName())); + } else { + method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString())); + } + builder.startStatement(); String fieldName = var.getSimpleName().toString(); - NodeChildData child = node.findChild(fieldName); - CodeTree init = createStaticCast(builder, child, fieldName); init = createAdoptChild(builder, var.asType(), init); @@ -1327,8 +1274,6 @@ builder.startStaticCall(getContext().getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end(); builder.end(); - emitSpecializationListeners(builder, node); - String currentNode = "this"; for (SpecializationData specialization : node.getSpecializations()) { if (!specialization.getExceptions().isEmpty()) { @@ -1352,7 +1297,7 @@ boolean firstUnreachable = true; for (SpecializationData current : node.getSpecializations()) { - if (current.isUninitialized() || current.isReachable()) { + if (current.isReachable()) { continue; } if (firstUnreachable) { @@ -1369,7 +1314,7 @@ List specializations = node.getSpecializations(); List filteredSpecializations = new ArrayList<>(); for (SpecializationData current : specializations) { - if (current.isUninitialized() || !current.isReachable()) { + if (current.isUninitialized() || current.isPolymorphic() || !current.isReachable()) { continue; } filteredSpecializations.add(current); @@ -1402,7 +1347,7 @@ private void emitUnreachableSpecializations(final CodeTreeBuilder builder, NodeData node) { for (SpecializationData current : node.getSpecializations()) { - if (current.isUninitialized() || current.isReachable()) { + if (current.isReachable()) { continue; } builder.string("// unreachable ").string(current.getId()).newLine(); @@ -1520,19 +1465,15 @@ } } - NodeChildData child = node.findChild(valueParam.getSpecification().getName()); - if (child == null) { - throw new IllegalStateException(); - } - - CodeTree implicitGuard = createTypeGuard(guardsBuilder, child, valueParam, typeGuard.getType(), typedCasts); + NodeExecutionData execution = valueParam.getSpecification().getExecution(); + CodeTree implicitGuard = createTypeGuard(guardsBuilder, execution, valueParam, typeGuard.getType(), typedCasts); if (implicitGuard != null) { guardsBuilder.string(guardsAnd); guardsBuilder.tree(implicitGuard); guardsAnd = " && "; } - CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType(), checkMinimumState, typedCasts); + CodeTree cast = createCast(castBuilder, execution, valueParam, typeGuard.getType(), checkMinimumState, typedCasts); if (cast != null) { castBuilder.tree(cast); } @@ -1604,8 +1545,8 @@ return false; } - private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean typedCasts) { - NodeData node = field.getNodeData(); + private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean typedCasts) { + NodeData node = execution.getChild().getNodeData(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); @@ -1617,7 +1558,7 @@ builder.startGroup(); - if (field.isShortCircuit()) { + if (execution.isShortCircuit()) { ActualParameter shortCircuit = source.getPreviousParameter(); assert shortCircuit != null; builder.string("("); @@ -1644,7 +1585,7 @@ } builder.end().end(); // call - if (field.isShortCircuit()) { + if (execution.isShortCircuit()) { builder.string(")"); } @@ -1654,8 +1595,8 @@ } // TODO merge redundancies with #createTypeGuard - private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean checkMinimumState, boolean typedCasts) { - NodeData node = field.getNodeData(); + private CodeTree createCast(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean checkMinimumState, boolean typedCasts) { + NodeData node = execution.getChild().getNodeData(); TypeData sourceType = source.getTypeSystemType(); if (!sourceType.needsCastTo(getContext(), targetType)) { @@ -1663,7 +1604,7 @@ } CodeTree condition = null; - if (field.isShortCircuit()) { + if (execution.isShortCircuit()) { ActualParameter shortCircuit = source.getPreviousParameter(); assert shortCircuit != null; condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); @@ -1777,7 +1718,7 @@ } builder.end(); builder.startDoWhile(); - builder.string("!").startParantheses().instanceOf("root", nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).end(); + builder.string("!").startParantheses().instanceOf("root", nodePolymorphicClassName(node)).end(); builder.end(); return builder.getRoot(); } @@ -1836,11 +1777,8 @@ replaceCall.startCall("replace"); } replaceCall.startGroup().startNew(className).string(source); - for (ActualParameter param : current.getParameters()) { - if (!param.getSpecification().isSignature()) { - continue; - } - NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); + for (ActualParameter param : current.getSignatureParameters()) { + NodeChildData child = param.getSpecification().getExecution().getChild(); List types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); if (types.size() > 1) { replaceCall.string(implicitTypeName(param)); @@ -1858,7 +1796,7 @@ } private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node, String currentNode) { - String polyClassName = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization()); + String polyClassName = nodePolymorphicClassName(node); String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization()); CodeTreeBuilder builder = parent.create(); @@ -1869,7 +1807,7 @@ builder.startStatement().startCall("currentCopy", "setNext0").startNew(uninitializedName).string(currentNode).end().end().end(); builder.startReturn(); - builder.startCall("currentCopy.next0", executeCachedName(node.getGenericPolymorphicSpecialization())); + builder.startCall("currentCopy.next0", EXECUTE_POLYMORPHIC_NAME); addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, true, null); builder.end(); builder.end(); @@ -1877,14 +1815,6 @@ return builder.getRoot(); } - private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { - for (TemplateMethod listener : node.getSpecializationListeners()) { - builder.startStatement(); - builder.tree(createTemplateMethodCall(builder, null, listener, listener, null)); - builder.end(); // statement - } - } - protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) { TypeData type = executable.getType(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); @@ -1897,11 +1827,7 @@ boolean returnVoid = type.isVoid(); List executeParameters = new ArrayList<>(); - for (ActualParameter sourceParameter : executable.getParameters()) { - if (!sourceParameter.getSpecification().isSignature()) { - continue; - } - + for (ActualParameter sourceParameter : executable.getSignatureParameters()) { ActualParameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName()); if (targetParameter != null) { executeParameters.add(targetParameter); @@ -1968,14 +1894,13 @@ protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List targetParameters, ActualParameter unexpectedParameter) { CodeTreeBuilder builder = parent.create(); - NodeData node = specialization.getNode(); for (ActualParameter targetParameter : targetParameters) { - NodeChildData child = node.findChild(targetParameter.getSpecification().getName()); if (!targetParameter.getSpecification().isSignature()) { continue; } - CodeTree executionExpressions = createExecuteChild(builder, child, sourceExecutable, targetParameter, unexpectedParameter); - CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, specialization, sourceExecutable, targetParameter, isShortCircuit(child), unexpectedParameter); + NodeExecutionData execution = targetParameter.getSpecification().getExecution(); + CodeTree executionExpressions = createExecuteChild(builder, execution, sourceExecutable, targetParameter, unexpectedParameter); + CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, specialization, sourceExecutable, targetParameter, execution.isShortCircuit(), unexpectedParameter); CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, specialization, targetParameter, unexpectedParameter); if (shortCircuitTree == executionExpressions) { @@ -1993,15 +1918,16 @@ return builder.getRoot(); } - private ExecutableTypeData resolveExecutableType(NodeChildData child, TypeData type) { - ExecutableTypeData targetExecutable = child.findExecutableType(getContext(), type); + private ExecutableTypeData resolveExecutableType(NodeExecutionData execution, TypeData type) { + ExecutableTypeData targetExecutable = execution.getChild().findExecutableType(getContext(), type); if (targetExecutable == null) { - targetExecutable = child.findAnyGenericExecutableType(getContext()); + targetExecutable = execution.getChild().findAnyGenericExecutableType(getContext()); } return targetExecutable; } - private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ActualParameter targetParameter, ActualParameter unexpectedParameter) { + private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, ActualParameter targetParameter, + ActualParameter unexpectedParameter) { SpecializationData specialization = getModel(); TreeSet possiblePolymorphicTypes = lookupPolymorphicTargetTypes(targetParameter); if (specialization.isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null && possiblePolymorphicTypes.size() > 1) { @@ -2020,28 +1946,25 @@ builder.string(polymorphicTypeName(targetParameter)).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType()); builder.end().startBlock(); builder.startStatement(); - builder.tree(createExecuteChildExpression(parent, child, sourceType, new ActualParameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null)); + builder.tree(createExecuteChildExpression(parent, execution, sourceType, new ActualParameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null)); builder.end(); builder.end(); } builder.startElseBlock(); - builder.startStatement().tree(createExecuteChildImplicit(parent, child, sourceExecutable, targetParameter, unexpectedParameter)).end(); + builder.startStatement().tree(createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter)).end(); builder.end(); return builder.getRoot(); } else { - return createExecuteChildImplicit(parent, child, sourceExecutable, targetParameter, unexpectedParameter); + return createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter); } } protected final List getImplicitTypeParamters(SpecializationData model) { List parameter = new ArrayList<>(); - for (ActualParameter param : model.getParameters()) { - if (!param.getSpecification().isSignature()) { - continue; - } - NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); + for (ActualParameter param : model.getSignatureParameters()) { + NodeChildData child = param.getSpecification().getExecution().getChild(); List types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); if (types.size() > 1) { parameter.add(param); @@ -2065,7 +1988,7 @@ return possiblePolymorphicTypes; } - private CodeTree createExecuteChildImplicit(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ActualParameter param, ActualParameter unexpectedParameter) { + private CodeTree createExecuteChildImplicit(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, ActualParameter param, ActualParameter unexpectedParameter) { CodeTreeBuilder builder = parent.create(); ActualParameter sourceParameter = sourceExecutable.findParameter(param.getLocalName()); String childExecuteName = createExecuteChildMethodName(param, sourceParameter != null); @@ -2089,19 +2012,20 @@ builder.end(); } else { - List sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); + List sourceTypes = execution.getChild().getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; if (sourceTypes.size() > 1) { builder.tree(createExecuteChildImplicitExpressions(parent, param, expectType)); } else { - builder.tree(createExecuteChildExpression(parent, child, expectType, param, unexpectedParameter, null)); + builder.tree(createExecuteChildExpression(parent, execution, expectType, param, unexpectedParameter, null)); } } return builder.getRoot(); } private String createExecuteChildMethodName(ActualParameter param, boolean expect) { - NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); + NodeExecutionData execution = param.getSpecification().getExecution(); + NodeChildData child = execution.getChild(); if (child.getExecuteWith().size() > 0) { return null; } @@ -2110,7 +2034,8 @@ return null; } String prefix = expect ? "expect" : "execute"; - return prefix + Utils.firstLetterUpperCase(child.getName()) + Utils.firstLetterUpperCase(Utils.getSimpleName(param.getType())) + param.getSpecificationIndex(); + String suffix = execution.getIndex() > -1 ? String.valueOf(execution.getIndex()) : ""; + return prefix + Utils.firstLetterUpperCase(child.getName()) + Utils.firstLetterUpperCase(Utils.getSimpleName(param.getType())) + suffix; } private List createExecuteChilds(ActualParameter param, Set expectTypes) { @@ -2155,7 +2080,7 @@ private CodeTree createExecuteChildImplicitExpressions(CodeTreeBuilder parent, ActualParameter targetParameter, TypeData expectType) { CodeTreeBuilder builder = parent.create(); NodeData node = getModel().getNode(); - NodeChildData child = node.findChild(targetParameter.getSpecification().getName()); + NodeExecutionData execution = targetParameter.getSpecification().getExecution(); List sourceTypes = node.getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType()); boolean elseIf = false; int index = 0; @@ -2169,18 +2094,18 @@ builder.startElseBlock(); } - ExecutableTypeData implictExecutableTypeData = child.findExecutableType(getContext(), sourceType); + ExecutableTypeData implictExecutableTypeData = execution.getChild().findExecutableType(getContext(), sourceType); if (implictExecutableTypeData == null) { /* * For children with executeWith.size() > 0 an executable type may not exist so * use the generic executable type which is guaranteed to exist. An expect call * is inserted automatically by #createExecuteExpression. */ - implictExecutableTypeData = child.getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), child.getExecuteWith().size()); + implictExecutableTypeData = execution.getChild().getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), execution.getChild().getExecuteWith().size()); } - ImplicitCastData cast = child.getNodeData().getTypeSystem().lookupCast(sourceType, targetParameter.getTypeSystemType()); - CodeTree execute = createExecuteChildExpression(builder, child, expectType, targetParameter, null, cast); + ImplicitCastData cast = execution.getChild().getNodeData().getTypeSystem().lookupCast(sourceType, targetParameter.getTypeSystemType()); + CodeTree execute = createExecuteChildExpression(builder, execution, expectType, targetParameter, null, cast); builder.statement(execute); builder.end(); index++; @@ -2188,8 +2113,8 @@ return builder.getRoot(); } - private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData child, TypeData sourceParameterType, ActualParameter targetParameter, ActualParameter unexpectedParameter, - ImplicitCastData cast) { + private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData execution, TypeData sourceParameterType, ActualParameter targetParameter, + ActualParameter unexpectedParameter, ImplicitCastData cast) { // assignments: targetType <- castTargetType <- castSourceType <- sourceType TypeData sourceType = sourceParameterType; TypeData targetType = targetParameter.getTypeSystemType(); @@ -2203,15 +2128,15 @@ CodeTree expression; if (sourceType == null) { - ExecutableTypeData targetExecutable = resolveExecutableType(child, castSourceType); - expression = createExecuteChildExpression(parent, child, targetParameter, targetExecutable, unexpectedParameter); + ExecutableTypeData targetExecutable = resolveExecutableType(execution, castSourceType); + expression = createExecuteChildExpression(parent, execution, targetExecutable, unexpectedParameter); sourceType = targetExecutable.getType(); } else { expression = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)); } // target = expectTargetType(implicitCast(expectCastSourceType(source))) - TypeSystemData typeSystem = child.getNodeData().getTypeSystem(); + TypeSystemData typeSystem = execution.getChild().getNodeData().getTypeSystem(); expression = createExpectType(typeSystem, sourceType, castSourceType, expression); expression = createImplicitCast(parent, typeSystem, cast, expression); expression = createExpectType(typeSystem, castTargetType, targetType, expression); @@ -2248,32 +2173,32 @@ } private boolean hasUnexpected(ActualParameter sourceParameter, ActualParameter targetParameter, ActualParameter unexpectedParameter) { - NodeChildData child = getModel().getNode().findChild(targetParameter.getSpecification().getName()); + NodeExecutionData execution = targetParameter.getSpecification().getExecution(); if (getModel().isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) { // check for other polymorphic types TreeSet polymorphicTargetTypes = lookupPolymorphicTargetTypes(targetParameter); if (polymorphicTargetTypes.size() > 1) { for (TypeData polymorphicTargetType : polymorphicTargetTypes) { - if (hasUnexpectedType(child, sourceParameter, polymorphicTargetType)) { + if (hasUnexpectedType(execution, sourceParameter, polymorphicTargetType)) { return true; } } } } - if (hasUnexpectedType(child, sourceParameter, targetParameter.getTypeSystemType())) { + if (hasUnexpectedType(execution, sourceParameter, targetParameter.getTypeSystemType())) { return true; } return false; } - private boolean hasUnexpectedType(NodeChildData child, ActualParameter sourceParameter, TypeData targetType) { + private boolean hasUnexpectedType(NodeExecutionData execution, ActualParameter sourceParameter, TypeData targetType) { List implicitSourceTypes = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType); for (TypeData implicitSourceType : implicitSourceTypes) { TypeData sourceType; - ExecutableTypeData targetExecutable = resolveExecutableType(child, implicitSourceType); + ExecutableTypeData targetExecutable = resolveExecutableType(execution, implicitSourceType); if (sourceParameter != null) { sourceType = sourceParameter.getTypeSystemType(); } else { @@ -2336,8 +2261,7 @@ private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, ActualParameter param) { NodeData node = specialization.getNode(); - assert !node.getPolymorphicSpecializations().isEmpty(); - SpecializationData generic = node.getGenericPolymorphicSpecialization(); + SpecializationData polymorphic = node.getPolymorphicSpecialization(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); builder.startStatement().string(polymorphicTypeName(param)).string(" = ").typeLiteral(getContext().getType(Object.class)).end(); @@ -2345,11 +2269,11 @@ builder.startReturn(); CodeTreeBuilder execute = new CodeTreeBuilder(builder); - execute.startCall("next0", executeCachedName(generic)); - addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true, null); + execute.startCall("next0", EXECUTE_POLYMORPHIC_NAME); + addInternalValueParameterNames(execute, specialization, polymorphic, param.getLocalName(), true, true, null); execute.end(); - TypeData sourceType = generic.getReturnType().getTypeSystemType(); + TypeData sourceType = polymorphic.getReturnType().getTypeSystemType(); builder.tree(createExpectExecutableType(node, sourceType, currentExecutable, execute.getRoot())); @@ -2357,11 +2281,10 @@ return builder.getRoot(); } - private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetChild, ActualParameter targetParameter, ExecutableTypeData targetExecutable, - ActualParameter unexpectedParameter) { + private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData targetExecution, ExecutableTypeData targetExecutable, ActualParameter unexpectedParameter) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (targetChild != null) { - builder.tree(createAccessChild(builder, targetChild, targetParameter)); + if (targetExecution != null) { + builder.tree(createAccessChild(builder, targetExecution)); builder.string("."); } @@ -2375,8 +2298,8 @@ builder.string(parameter.getLocalName()); } else { - if (index < targetChild.getExecuteWith().size()) { - NodeChildData child = targetChild.getExecuteWith().get(index); + if (index < targetExecution.getChild().getExecuteWith().size()) { + NodeChildData child = targetExecution.getChild().getExecuteWith().get(index); ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName()); List specializationParams = getModel().findParameters(spec); @@ -2415,31 +2338,31 @@ return builder.getRoot(); } - private CodeTree createAccessChild(CodeTreeBuilder parent, NodeChildData targetChild, ActualParameter targetParameter) throws AssertionError { + private CodeTree createAccessChild(CodeTreeBuilder parent, NodeExecutionData targetExecution) throws AssertionError { CodeTreeBuilder builder = parent.create(); - Element accessElement = targetChild.getAccessElement(); + Element accessElement = targetExecution.getChild().getAccessElement(); if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) { - builder.string("this.").string(targetChild.getName()); + builder.string("this.").string(targetExecution.getChild().getName()); } else if (accessElement.getKind() == ElementKind.FIELD) { builder.string("this.").string(accessElement.getSimpleName().toString()); } else { throw new AssertionError(); } - if (targetParameter.getSpecification().isIndexed()) { - builder.string("[" + targetParameter.getSpecificationIndex() + "]"); + if (targetExecution.isIndexed()) { + builder.string("[" + targetExecution.getIndex() + "]"); } return builder.getRoot(); } private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) { - NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName()); - if (!isShortCircuit(forField)) { + NodeExecutionData execution = parameter.getSpecification().getExecution(); + if (execution == null || !execution.isShortCircuit()) { return body; } CodeTreeBuilder builder = new CodeTreeBuilder(parent); ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter); - builder.tree(createShortCircuitValue(builder, specialization, forField, shortCircuitParam, exceptionParam)); + builder.tree(createShortCircuitValue(builder, specialization, execution, shortCircuitParam, exceptionParam)); builder.declaration(parameter.getType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getType())); builder.startIf().string(shortCircuitParam.getLocalName()).end(); builder.startBlock(); @@ -2454,16 +2377,13 @@ return builder.getRoot(); } - private boolean isShortCircuit(NodeChildData forField) { - return forField != null && forField.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT; - } - - private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeChildData forField, ActualParameter shortCircuitParam, ActualParameter exceptionParam) { + private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeExecutionData execution, ActualParameter shortCircuitParam, + ActualParameter exceptionParam) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); int shortCircuitIndex = 0; - for (NodeChildData field : specialization.getNode().getChildren()) { - if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) { - if (field == forField) { + for (NodeExecutionData otherExectuion : specialization.getNode().getChildExecutions()) { + if (otherExectuion.isShortCircuit()) { + if (otherExectuion == execution) { break; } shortCircuitIndex++; @@ -2543,7 +2463,7 @@ if (nodeGen != null) { baseType = nodeGen.asType(); } - CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node, polymorph), baseType, false); + CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false); clazz.getAnnotationMirrors().add(createNodeInfo(node, Kind.POLYMORPHIC)); @@ -2640,8 +2560,12 @@ kind = Kind.GENERIC; } else if (specialization.isUninitialized()) { kind = Kind.UNINITIALIZED; + } else if (specialization.isPolymorphic()) { + kind = Kind.POLYMORPHIC; + } else if (specialization.isSpecialized()) { + kind = Kind.SPECIALIZED; } else { - kind = Kind.SPECIALIZED; + throw new AssertionError(); } clazz.getAnnotationMirrors().add(createNodeInfo(node, kind)); @@ -2747,9 +2671,9 @@ CodeTypeElement clazz = getElement(); - final SpecializationData polymorphic = node.getGenericPolymorphicSpecialization(); - - ExecutableElement executeCached = nodeGen.getMethod(executeCachedName(polymorphic)); + final SpecializationData polymorphic = node.getPolymorphicSpecialization(); + + ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_POLYMORPHIC_NAME); // ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached, // node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType()); @@ -2767,7 +2691,7 @@ builder.tree(createAppendPolymorphic(builder, specialization)); } else { CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); - elseBuilder.startReturn().startCall("this.next0", executeCachedName(polymorphic)); + elseBuilder.startReturn().startCall("this.next0", EXECUTE_POLYMORPHIC_NAME); addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true, null); elseBuilder.end().end(); @@ -2797,7 +2721,7 @@ builder.startBlock(); String message = "Polymorphic limit reached (" + node.getPolymorphicDepth() + ")"; String castRoot = "(" + baseClassName(node) + ") root"; - builder.tree(createGenericInvoke(builder, node.getGenericPolymorphicSpecialization(), node.getGenericSpecialization(), + builder.tree(createGenericInvoke(builder, node.getPolymorphicSpecialization(), node.getGenericSpecialization(), createReplaceCall(builder, node.getGenericSpecialization(), "root", castRoot, message), null)); builder.end(); @@ -2815,7 +2739,7 @@ builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot()); - CodeTree root = builder.create().cast(nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).string("root").getRoot(); + CodeTree root = builder.create().cast(nodePolymorphicClassName(node)).string("root").getRoot(); builder.startIf().string("this.next0 != null").end().startBlock(); builder.startStatement().string("(").tree(root).string(").").startCall(UPDATE_TYPES_NAME).tree(root).end().end(); builder.end(); @@ -2856,39 +2780,43 @@ int signatureIndex = -1; for (VariableElement param : method.getParameters()) { CodeVariableElement var = CodeVariableElement.clone(param); - ActualParameter actualParameter = execType.getParameters().get(i); - if (actualParameter.getSpecification().isSignature()) { - signatureIndex++; - } - + ActualParameter actualParameter = i < execType.getParameters().size() ? execType.getParameters().get(i) : null; String name; - if (evaluated && actualParameter.getSpecification().isSignature()) { - name = valueNameEvaluated(actualParameter); - } else { - name = valueName(actualParameter); - } - - int varArgCount = getModel().getSignatureSize() - signatureIndex; - if (evaluated && actualParameter.isVarArgs()) { - ActualParameter baseVarArgs = actualParameter; - name = valueName(baseVarArgs) + "Args"; - - builder.startAssert().string(name).string(" != null").end(); - builder.startAssert().string(name).string(".length == ").string(String.valueOf(varArgCount)).end(); - if (varArgCount > 0) { - List varArgsParameter = execType.getParameters().subList(i, execType.getParameters().size()); - for (ActualParameter varArg : varArgsParameter) { - if (varArgCount <= 0) { - break; + if (actualParameter != null) { + if (actualParameter.getSpecification().isSignature()) { + signatureIndex++; + } + + if (evaluated && actualParameter.getSpecification().isSignature()) { + name = valueNameEvaluated(actualParameter); + } else { + name = valueName(actualParameter); + } + + int varArgCount = getModel().getSignatureSize() - signatureIndex; + if (evaluated && actualParameter.isTypeVarArgs()) { + ActualParameter baseVarArgs = actualParameter; + name = valueName(baseVarArgs) + "Args"; + + builder.startAssert().string(name).string(" != null").end(); + builder.startAssert().string(name).string(".length == ").string(String.valueOf(varArgCount)).end(); + if (varArgCount > 0) { + List varArgsParameter = execType.getParameters().subList(i, execType.getParameters().size()); + for (ActualParameter varArg : varArgsParameter) { + if (varArgCount <= 0) { + break; + } + TypeMirror type = baseVarArgs.getType(); + if (type.getKind() == TypeKind.ARRAY) { + type = ((ArrayType) type).getComponentType(); + } + builder.declaration(type, valueNameEvaluated(varArg), name + "[" + varArg.getTypeVarArgsIndex() + "]"); + varArgCount--; } - TypeMirror type = baseVarArgs.getType(); - if (type.getKind() == TypeKind.ARRAY) { - type = ((ArrayType) type).getComponentType(); - } - builder.declaration(type, valueNameEvaluated(varArg), name + "[" + varArg.getVarArgsIndex() + "]"); - varArgCount--; } } + } else { + name = "arg" + i; } var.setName(name); method.getParameters().set(i, var); @@ -2984,7 +2912,7 @@ CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); if (specialization.isPolymorphic()) { - returnBuilder.startCall("next0", executeCachedName(specialization)); + returnBuilder.startCall("next0", EXECUTE_POLYMORPHIC_NAME); addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true, null); returnBuilder.end(); } else if (specialization.isUninitialized()) { diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java Tue Jan 07 18:53:04 2014 +0100 @@ -28,54 +28,61 @@ import javax.lang.model.type.*; import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.node.NodeChildData.*; import com.oracle.truffle.dsl.processor.template.*; import com.oracle.truffle.dsl.processor.typesystem.*; public class NodeData extends Template implements Comparable { private final String nodeId; + private final String shortName; + private final List enclosingNodes = new ArrayList<>(); private NodeData declaringNode; - private List declaredNodes = new ArrayList<>(); - private boolean nodeContainer; - private TypeSystemData typeSystem; - private List children; - private List fields; - private TypeMirror nodeType; + private final TypeSystemData typeSystem; + private final List children; + private final List childExecutions; + private final List fields; + private final List assumptions; + private ParameterSpec instanceParameterSpec; - private List specializations; - private List polymorphicSpecializations; - private SpecializationData genericPolymorphicSpecialization; - private List specializationListeners; + private final List specializations = new ArrayList<>(); + private final List shortCircuits = new ArrayList<>(); + private final List casts = new ArrayList<>(); private Map> executableTypes; - private List shortCircuits; - private List assumptions; - private List casts; private int polymorphicDepth = -1; - private String shortName; - public NodeData(TypeElement type, String id) { + public NodeData(TypeElement type, String shortName, TypeSystemData typeSystem, List children, List executions, List fields, + List assumptions, int polymorphicDepth) { super(type, null, null); - this.nodeId = id; + this.nodeId = type.getSimpleName().toString(); + this.shortName = shortName; + this.typeSystem = typeSystem; + this.fields = fields; + this.children = children; + this.childExecutions = executions; + this.assumptions = assumptions; + this.polymorphicDepth = polymorphicDepth; + + if (children != null) { + for (NodeChildData child : children) { + child.setParentNode(this); + } + } } - public NodeData(NodeData splitSource, String templateMethodName, String nodeId) { - super(splitSource.getTemplateType(), templateMethodName, null); - this.nodeId = nodeId; - this.declaringNode = splitSource.declaringNode; - this.declaredNodes = splitSource.declaredNodes; - this.typeSystem = splitSource.typeSystem; - this.nodeType = splitSource.nodeType; - this.specializations = splitSource.specializations; - this.specializationListeners = splitSource.specializationListeners; - this.executableTypes = splitSource.executableTypes; - this.shortCircuits = splitSource.shortCircuits; - this.fields = splitSource.fields; - this.children = splitSource.children; - this.assumptions = splitSource.assumptions; + public NodeData(TypeElement type) { + this(type, null, null, null, null, null, null, -1); + } + + public void addEnclosedNode(NodeData node) { + this.enclosingNodes.add(node); + node.declaringNode = this; + } + + public List getChildExecutions() { + return childExecutions; } public int getSignatureSize() { @@ -114,7 +121,7 @@ return polymorphicDepth > 1; } - void setPolymorphicDepth(int polymorphicDepth) { + public void setPolymorphicDepth(int polymorphicDepth) { this.polymorphicDepth = polymorphicDepth; } @@ -122,43 +129,19 @@ return casts; } - void setCasts(List casts) { - this.casts = casts; - } - - void setShortName(String shortName) { - this.shortName = shortName; - } - public String getShortName() { return shortName; } - public boolean isNodeContainer() { - return nodeContainer; - } - - void setTypeSystem(TypeSystemData typeSystem) { - this.typeSystem = typeSystem; - } - - void setFields(List fields) { - this.fields = fields; - } - public List getFields() { return fields; } - void setNodeContainer(boolean splitByMethodName) { - this.nodeContainer = splitByMethodName; - } - @Override protected List findChildContainers() { List containerChildren = new ArrayList<>(); - if (declaredNodes != null) { - containerChildren.addAll(declaredNodes); + if (enclosingNodes != null) { + containerChildren.addAll(enclosingNodes); } if (typeSystem != null) { containerChildren.add(typeSystem); @@ -170,9 +153,6 @@ } } } - if (specializationListeners != null) { - containerChildren.addAll(specializationListeners); - } if (executableTypes != null) { containerChildren.addAll(getExecutableTypes()); } @@ -204,16 +184,9 @@ } public TypeMirror getNodeType() { - if (nodeType != null) { - return nodeType; - } return getTemplateType().asType(); } - void setAssumptions(List assumptions) { - this.assumptions = assumptions; - } - public List getAssumptions() { return assumptions; } @@ -228,7 +201,7 @@ boolean noSpecialization = true; for (SpecializationData specialization : specializations) { - noSpecialization = noSpecialization && specialization.isGeneric() || specialization.isUninitialized(); + noSpecialization = noSpecialization && !specialization.isSpecialized(); } return !noSpecialization; } @@ -246,7 +219,7 @@ public List getNodeDeclaringChildren() { List nodeChildren = new ArrayList<>(); - for (NodeData child : getDeclaredNodes()) { + for (NodeData child : getEnclosingNodes()) { if (child.needsFactory()) { nodeChildren.add(child); } @@ -255,24 +228,12 @@ return nodeChildren; } - void setDeclaredNodes(List declaredChildren) { - this.declaredNodes = declaredChildren; - - for (NodeData child : declaredChildren) { - child.declaringNode = this; - } - } - - public NodeData getParent() { + public NodeData getDeclaringNode() { return declaringNode; } - public List getDeclaredNodes() { - return declaredNodes; - } - - public void setNodeType(TypeMirror nodeType) { - this.nodeType = nodeType; + public List getEnclosingNodes() { + return enclosingNodes; } public List getAllTemplateMethods() { @@ -282,7 +243,6 @@ methods.add(specialization); } - methods.addAll(getSpecializationListeners()); methods.addAll(getExecutableTypes()); methods.addAll(getShortCircuits()); if (getCasts() != null) { @@ -374,16 +334,6 @@ return result; } - public NodeChildData[] filterFields(ExecutionKind usage) { - List filteredFields = new ArrayList<>(); - for (NodeChildData field : getChildren()) { - if (usage == null || field.getExecutionKind() == usage) { - filteredFields.add(field); - } - } - return filteredFields.toArray(new NodeChildData[filteredFields.size()]); - } - public boolean needsRewrites(ProcessorContext context) { boolean needsRewrites = false; @@ -396,6 +346,15 @@ return needsRewrites || getSpecializations().size() > 1; } + public SpecializationData getPolymorphicSpecialization() { + for (SpecializationData specialization : specializations) { + if (specialization.isPolymorphic()) { + return specialization; + } + } + return null; + } + public SpecializationData getGenericSpecialization() { for (SpecializationData specialization : specializations) { if (specialization.isGeneric()) { @@ -438,13 +397,12 @@ dumpProperty(builder, indent, "executableTypes", getExecutableTypes()); dumpProperty(builder, indent, "specializations", getSpecializations()); dumpProperty(builder, indent, "polymorphicDepth", getPolymorphicDepth()); - dumpProperty(builder, indent, "polymorphic", getPolymorphicSpecializations()); dumpProperty(builder, indent, "assumptions", getAssumptions()); dumpProperty(builder, indent, "casts", getCasts()); dumpProperty(builder, indent, "messages", collectMessages()); - if (getDeclaredNodes().size() > 0) { + if (getEnclosingNodes().size() > 0) { builder.append(String.format("\n%s children = [", indent)); - for (NodeData node : getDeclaredNodes()) { + for (NodeData node : getEnclosingNodes()) { builder.append("\n"); builder.append(node.dump(level + 1)); } @@ -490,6 +448,18 @@ return b.toString(); } + public NodeExecutionData findExecution(String name) { + if (getChildExecutions() == null) { + return null; + } + for (NodeExecutionData execution : getChildExecutions()) { + if (execution.getName().equals(name)) { + return execution; + } + } + return null; + } + public NodeChildData findChild(String name) { for (NodeChildData field : getChildren()) { if (field.getName().equals(name)) { @@ -503,30 +473,8 @@ return children; } - void setChildren(List fields) { - this.children = fields; - } - public List getSpecializations() { - return getSpecializations(false); - } - - public List getSpecializations(boolean userDefinedOnly) { - if (userDefinedOnly) { - List specs = new ArrayList<>(); - for (SpecializationData spec : specializations) { - if (spec.getMethod() != null) { - specs.add(spec); - } - } - return specs; - } else { - return specializations; - } - } - - public List getSpecializationListeners() { - return specializationListeners; + return specializations; } public List getExecutableTypes() { @@ -537,43 +485,10 @@ return shortCircuits; } - void setSpecializations(List specializations) { - this.specializations = specializations; - if (this.specializations != null) { - for (SpecializationData specialization : specializations) { - specialization.setNode(this); - } - } - } - - void setPolymorphicSpecializations(List polymorphicSpecializations) { - this.polymorphicSpecializations = polymorphicSpecializations; - } - - public List getPolymorphicSpecializations() { - return polymorphicSpecializations; - } - - void setGenericPolymorphicSpecialization(SpecializationData genericPolymoprhicSpecialization) { - this.genericPolymorphicSpecialization = genericPolymoprhicSpecialization; - } - - public SpecializationData getGenericPolymorphicSpecialization() { - return genericPolymorphicSpecialization; - } - - void setSpecializationListeners(List specializationListeners) { - this.specializationListeners = specializationListeners; - } - - void setExecutableTypes(Map> executableTypes) { + public void setExecutableTypes(Map> executableTypes) { this.executableTypes = executableTypes; } - void setShortCircuits(List shortCircuits) { - this.shortCircuits = shortCircuits; - } - @Override public String toString() { return getClass().getSimpleName() + "[" + getNodeId() + "]"; @@ -593,4 +508,5 @@ public int compareTo(NodeData o) { return getNodeId().compareTo(o.getNodeId()); } + } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeExecutionData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeExecutionData.java Tue Jan 07 18:53:04 2014 +0100 @@ -0,0 +1,92 @@ +/* + * 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.dsl.processor.node; + +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.node.NodeChildData.*; + +public class NodeExecutionData { + + private final NodeChildData child; + private final String name; + private final int index; + private final boolean shortCircuit; + + public NodeExecutionData(NodeChildData child, int index, boolean shortCircuit) { + this.child = child; + this.index = index; + this.shortCircuit = shortCircuit; + this.name = createName(); + } + + private String createName() { + if (isIndexed()) { + return child.getName() + index; + } + return child.getName(); + } + + public TypeMirror getNodeType() { + TypeMirror type; + if (child.getCardinality() == Cardinality.MANY && child.getNodeType().getKind() == TypeKind.ARRAY) { + type = ((ArrayType) child.getNodeType()).getComponentType(); + } else { + type = child.getNodeType(); + } + return type; + } + + public String getName() { + return name; + } + + public NodeChildData getChild() { + return child; + } + + public int getIndex() { + return index; + } + + public boolean isIndexed() { + return index > -1; + } + + public boolean isShortCircuit() { + return shortCircuit; + } + + public String getShortCircuitId() { + return createShortCircuitId(child, index); + } + + public static String createShortCircuitId(NodeChildData child, int varArgsIndex) { + String shortCircuitName = child.getName(); + if (child.getCardinality().isMany()) { + shortCircuitName = shortCircuitName + "[" + varArgsIndex + "]"; + } + return shortCircuitName; + } + +} diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java Tue Jan 07 18:53:04 2014 +0100 @@ -28,7 +28,6 @@ import javax.lang.model.type.*; import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.node.NodeChildData.*; import com.oracle.truffle.dsl.processor.template.*; public abstract class NodeMethodParser extends TemplateMethodParser { @@ -41,10 +40,9 @@ return template; } - @SuppressWarnings("unused") - protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, int evaluatedCount) { - ParameterSpec spec = new ParameterSpec(valueName, nodeTypeMirrors(nodeData)); - spec.setSignature(true); + protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) { + ParameterSpec spec = new ParameterSpec(execution.getName(), nodeTypeMirrors(execution.getChild().getNodeData())); + spec.setExecution(execution); return spec; } @@ -61,7 +59,7 @@ } protected ParameterSpec createReturnParameterSpec() { - return createValueParameterSpec("returnValue", getNode(), 0); + return new ParameterSpec("returnValue", nodeTypeMirrors(getNode())); } @Override @@ -85,31 +83,21 @@ return methodSpec; } - public void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec methodSpec) { - // children are null when parsing executable types - if (getNode().getChildren() != null) { - for (NodeChildData child : getNode().getChildren()) { - String valueName = child.getName(); - if (breakName != null && valueName.equals(breakName)) { - break; - } - if (child.getExecutionKind() == ExecutionKind.DEFAULT) { - ParameterSpec spec = createValueParameterSpec(child.getName(), child.getNodeData(), child.getExecuteWith().size()); - if (child.getCardinality().isMany()) { - spec.setCardinality(Cardinality.MANY); - spec.setIndexed(true); - } - methodSpec.addRequired(spec); - } else if (child.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) { + public void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec spec) { + if (getNode().getChildren() == null) { + // children are null when parsing executable types + return; + } - if (shortCircuitsEnabled) { - methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class))); - } - methodSpec.addRequired(createValueParameterSpec(valueName, child.getNodeData(), child.getExecuteWith().size())); - } else { - assert false; - } + for (NodeExecutionData execution : getNode().getChildExecutions()) { + if (breakName != null && execution.getShortCircuitId().equals(breakName)) { + break; } + + if (execution.isShortCircuit() && shortCircuitsEnabled) { + spec.addRequired(new ParameterSpec(shortCircuitValueName(execution.getName()), getContext().getType(boolean.class))); + } + spec.addRequired(createValueParameterSpec(execution)); } } @@ -121,7 +109,7 @@ protected void addDefaultFieldMethodSpec(MethodSpec methodSpec) { for (NodeFieldData field : getNode().getFields()) { - if (getNode().isNodeContainer() || field.getGetter() == null) { + if (field.getGetter() == null) { ParameterSpec spec = new ParameterSpec(field.getName(), field.getType()); spec.setLocal(true); methodSpec.addOptional(spec); @@ -130,6 +118,9 @@ } protected void addDefaultImplicitThis(ExecutableElement method, MethodSpec methodSpec) { + if (method == null) { + return; + } TypeMirror declaredType = Utils.findNearestEnclosingType(method).asType(); if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(getContext(), declaredType, getContext().getTruffleTypes().getNode())) { diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Tue Jan 07 18:53:04 2014 +0100 @@ -34,15 +34,15 @@ import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality; -import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind; +import com.oracle.truffle.dsl.processor.node.SpecializationData.*; import com.oracle.truffle.dsl.processor.template.*; -import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature; +import com.oracle.truffle.dsl.processor.template.TemplateMethod.TypeSignature; import com.oracle.truffle.dsl.processor.typesystem.*; -public class NodeParser extends TemplateParser { +public class NodeParser extends AbstractParser { - public static final List> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class, - NodeContainer.class, NodeChild.class, NodeChildren.class, NodeId.class); + public static final List> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class, + NodeChildren.class); private Map parsedNodes; @@ -52,7 +52,6 @@ @Override protected NodeData parse(Element element, AnnotationMirror mirror) { - assert element instanceof TypeElement; NodeData node = null; try { parsedNodes = new HashMap<>(); @@ -73,7 +72,7 @@ @Override protected NodeData filterErrorElements(NodeData model) { - for (Iterator iterator = model.getDeclaredNodes().iterator(); iterator.hasNext();) { + for (Iterator iterator = model.getEnclosingNodes().iterator(); iterator.hasNext();) { NodeData node = filterErrorElements(iterator.next()); if (node == null) { iterator.remove(); @@ -106,29 +105,27 @@ return parsedNodes.get(typeName); } - List types = ElementFilter.typesIn(rootType.getEnclosedElements()); - - List children = new ArrayList<>(); - for (TypeElement childElement : types) { - NodeData childNode = resolveNode(childElement); - if (childNode != null) { - children.add(childNode); + List enclosedNodes = new ArrayList<>(); + for (TypeElement enclosedType : ElementFilter.typesIn(rootType.getEnclosedElements())) { + NodeData enclosedChild = resolveNode(enclosedType); + if (enclosedChild != null) { + enclosedNodes.add(enclosedChild); } } - NodeData rootNode = parseNode(rootType); - if (rootNode == null && children.size() > 0) { - rootNode = new NodeData(rootType, rootType.getSimpleName().toString()); + NodeData node = parseNode(rootType); + if (node == null && !enclosedNodes.isEmpty()) { + node = new NodeData(rootType); } - parsedNodes.put(typeName, rootNode); - - if (rootNode != null) { - children.addAll(rootNode.getDeclaredNodes()); - rootNode.setDeclaredNodes(children); + if (node != null) { + for (NodeData enclosedNode : enclosedNodes) { + node.addEnclosedNode(enclosedNode); + } } - return rootNode; + parsedNodes.put(typeName, node); + return node; } private NodeData parseNode(TypeElement originalTemplateType) { @@ -140,174 +137,69 @@ return null; } - List lookupTypes = findSuperClasses(new ArrayList(), templateType); - Collections.reverse(lookupTypes); - - AnnotationMirror nodeClass = findFirstAnnotation(lookupTypes, NodeContainer.class); - TypeMirror nodeType = null; - if (Utils.isAssignable(context, templateType.asType(), context.getTruffleTypes().getNode())) { - nodeType = templateType.asType(); - } - if (nodeClass != null) { - nodeType = inheritType(nodeClass, "value", nodeType); - } - - if (nodeType == null) { + List lookupTypes = collectSuperClasses(new ArrayList(), templateType); + if (!Utils.isAssignable(context, templateType.asType(), context.getTruffleTypes().getNode())) { return null; } - Elements elementUtil = context.getEnvironment().getElementUtils(); - Set elementSet = new HashSet<>(elementUtil.getAllMembers(templateType)); - if (!Utils.typeEquals(templateType.asType(), nodeType)) { - elementSet.addAll(elementUtil.getAllMembers(Utils.fromTypeMirror(nodeType))); - - List nodeLookupTypes = findSuperClasses(new ArrayList(), Utils.fromTypeMirror(nodeType)); - Collections.reverse(nodeLookupTypes); - lookupTypes.addAll(nodeLookupTypes); + List elements = context.getEnvironment().getElementUtils().getAllMembers(templateType); - Set types = new HashSet<>(); - for (ListIterator iterator = lookupTypes.listIterator(); iterator.hasNext();) { - TypeElement typeElement = iterator.next(); - if (types.contains(typeElement)) { - iterator.remove(); - } else { - types.add(typeElement); - } - } - } - List elements = new ArrayList<>(elementSet); - - NodeData node = parseNodeData(templateType, nodeType, elements, lookupTypes); - + NodeData node = parseNodeData(templateType, elements, lookupTypes); if (node.hasErrors()) { return node; // error sync point } - parseMethods(node, elements); + initializeChildren(node); + + node.getSpecializations().addAll(new SpecializationMethodParser(context, node).parse(elements)); + node.getSpecializations().addAll(new GenericParser(context, node).parse(elements)); + node.getCasts().addAll(new CreateCastParser(context, node).parse(elements)); + node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(elements)); if (node.hasErrors()) { - return node; - } - - List nodes; - - if (node.isNodeContainer()) { - nodes = splitNodeData(node); - } else { - nodes = new ArrayList<>(); - nodes.add(node); + return node; // error sync point } - for (NodeData splittedNode : nodes) { - if (templateType.getModifiers().contains(Modifier.PRIVATE) && splittedNode.getSpecializations().size() > 0) { - splittedNode.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName()); - } + verifySpecializationSameLength(node); + initializeSpecializations(elements, node); + initializeShortCircuits(node); // requires specializations and polymorphic specializations - finalizeSpecializations(elements, splittedNode); - verifyNode(splittedNode, elements); - expandExecutableTypeVarArgs(splittedNode); - createPolymorphicSpecializations(splittedNode); - assignShortCircuitsToSpecializations(splittedNode); - } - - if (node.isNodeContainer()) { - node.setDeclaredNodes(nodes); - node.setSpecializationListeners(new ArrayList()); - node.setSpecializations(new ArrayList()); - } + verifyVisibilities(node); + verifySpecializationOrder(node); + verifyMissingAbstractMethods(node, elements); + verifyConstructors(node); + verifyNamingConvention(node.getShortCircuits(), "needs"); + verifySpecializationThrows(node); return node; } - private static void expandExecutableTypeVarArgs(NodeData node) { - for (ExecutableTypeData executableMethod : node.getExecutableTypes()) { - if (!(executableMethod.getMethod().isVarArgs() && executableMethod.getSpecification().isVariableRequiredArguments())) { - continue; - } - int expandArguments = node.getSignatureSize() - executableMethod.getSignatureSize(); - if (expandArguments > 0) { - int signatureSize = executableMethod.getSignatureSize(); - ActualParameter parameter = executableMethod.getSignatureParameter(signatureSize - 1); - for (int i = 0; i < expandArguments; i++) { - int newVarArgsIndex = parameter.getVarArgsIndex() + i + 1; - int newSpecificationIndex = parameter.getSpecificationIndex() + i + 1; - executableMethod.getParameters().add( - new ActualParameter(parameter.getSpecification(), parameter.getTypeSystemType(), newSpecificationIndex, newVarArgsIndex, parameter.isImplicit())); - } - - } - } - } - - private void createPolymorphicSpecializations(NodeData node) { - if (!node.needsRewrites(context) || !node.isPolymorphic()) { - node.setPolymorphicSpecializations(Collections. emptyList()); - return; - } - - SpecializationData generic = node.getGenericSpecialization(); - - List polymorphicSignature = new ArrayList<>(); - // TODO we should support more optimized for boxing - // List updatePolymorphic = generic.getReturnTypeAndParameters(); - List updatePolymorphic = Arrays.asList(); - for (ActualParameter genericParameter : updatePolymorphic) { - if (!genericParameter.getSpecification().isSignature()) { - continue; - } - - Set usedTypes = new HashSet<>(); - for (SpecializationData specialization : node.getSpecializations()) { - if (!specialization.isSpecialized()) { - continue; - } - ActualParameter parameter = specialization.findParameter(genericParameter.getLocalName()); - if (parameter == null) { - throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName()); - } - usedTypes.add(parameter.getTypeSystemType()); - } - - TypeData polymorphicType; - if (usedTypes.size() == 1) { - polymorphicType = usedTypes.iterator().next(); - } else { - polymorphicType = node.getTypeSystem().getGenericTypeData(); - } - polymorphicSignature.add(polymorphicType); - } - - SpecializationData specialization = new SpecializationData(generic, false, false, true); - specialization.updateSignature(new Signature(polymorphicSignature)); - specialization.setNode(node); - node.setGenericPolymorphicSpecialization(specialization); - // TODO remove polymoprhic specializations - node.setPolymorphicSpecializations(Collections. emptyList()); - } - - private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List elements, List typeHierarchy) { - NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString()); - + private NodeData parseNodeData(TypeElement templateType, List elements, List typeHierarchy) { AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); if (typeSystemMirror == null) { - nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(nodeType)); + NodeData nodeData = new NodeData(templateType); + nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(templateType)); return nodeData; } - TypeMirror typeSytemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value"); - final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true); + TypeMirror typeSystemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value"); + final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true); if (typeSystem == null) { - nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSytemType)); + NodeData nodeData = new NodeData(templateType); + nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSystemType)); return nodeData; } AnnotationMirror polymorphicMirror = findFirstAnnotation(typeHierarchy, PolymorphicLimit.class); + int polymorphicLimit = -1; if (polymorphicMirror != null) { AnnotationValue limitValue = Utils.getAnnotationValue(polymorphicMirror, "value"); - int polymorphicLimit = Utils.getAnnotationValue(Integer.class, polymorphicMirror, "value"); - if (polymorphicLimit < 1) { + int customPolymorphicLimit = Utils.getAnnotationValue(Integer.class, polymorphicMirror, "value"); + if (customPolymorphicLimit < 1) { + NodeData nodeData = new NodeData(templateType); nodeData.addError(limitValue, "Invalid polymorphic limit %s.", polymorphicLimit); + return nodeData; } - nodeData.setPolymorphicDepth(polymorphicLimit); + polymorphicLimit = customPolymorphicLimit; } List assumptionsList = new ArrayList<>(); @@ -325,22 +217,19 @@ } } AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class); + String shortName = null; if (nodeInfoMirror != null) { - nodeData.setShortName(Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName")); + shortName = Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"); } - nodeData.setAssumptions(new ArrayList<>(assumptionsList)); - nodeData.setNodeType(nodeType); - AnnotationMirror nodeContainer = findFirstAnnotation(typeHierarchy, NodeContainer.class); - nodeData.setNodeContainer(nodeContainer != null); - nodeData.setTypeSystem(typeSystem); - nodeData.setFields(parseFields(typeHierarchy, elements)); - nodeData.setChildren(parseChildren(nodeData, elements, typeHierarchy)); + List fields = parseFields(typeHierarchy, elements); + List children = parseChildren(elements, typeHierarchy); + List executions = parseExecutions(children, elements); + + NodeData nodeData = new NodeData(templateType, shortName, typeSystem, children, executions, fields, assumptionsList, polymorphicLimit); nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements))); - // resolveChildren invokes cyclic parsing. parsedNodes.put(Utils.getQualifiedName(templateType), nodeData); - resolveChildren(nodeData); return nodeData; } @@ -389,28 +278,7 @@ return fields; } - private void resolveChildren(NodeData node) { - for (NodeChildData nodeChild : node.getChildren()) { - NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(nodeChild.getNodeType())); - nodeChild.setNode(fieldNodeData); - if (fieldNodeData == null) { - nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(nodeChild.getNodeType())); - } else if (!Utils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) { - nodeChild.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(), - NodeChild.class.getSimpleName(), Utils.getSimpleName(node.getTypeSystem().getTemplateType()), Utils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType())); - } - if (fieldNodeData != null) { - List types = nodeChild.findGenericExecutableTypes(context); - if (types.isEmpty()) { - AnnotationValue executeWithValue = Utils.getAnnotationValue(nodeChild.getMessageAnnotation(), "executeWith"); - nodeChild.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", nodeChild.getExecuteWith().size(), - Utils.getSimpleName(nodeChild.getNodeType())); - } - } - } - } - - private List parseChildren(NodeData parent, List elements, final List typeHierarchy) { + 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); @@ -435,7 +303,6 @@ List typeHierarchyReversed = new ArrayList<>(typeHierarchy); Collections.reverse(typeHierarchyReversed); for (TypeElement type : typeHierarchyReversed) { - AnnotationMirror nodeClassMirror = Utils.findAnnotationMirror(processingEnv, type, NodeContainer.class); AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, type, NodeChildren.class); TypeMirror nodeClassType = type.getSuperclass(); @@ -443,10 +310,6 @@ nodeClassType = null; } - if (nodeClassMirror != null) { - nodeClassType = inheritType(nodeClassMirror, "value", nodeClassType); - } - List children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class); int index = 0; for (AnnotationMirror childMirror : children) { @@ -470,16 +333,13 @@ Element getter = findGetter(elements, name, childType); - ExecutionKind kind = ExecutionKind.DEFAULT; - if (shortCircuits.contains(name)) { - kind = ExecutionKind.SHORT_CIRCUIT; - } - - NodeChildData nodeChild = new NodeChildData(parent, type, childMirror, name, childType, originalChildType, getter, cardinality, kind); + NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality); parsedChildren.add(nodeChild); - verifyNodeChild(nodeChild); + if (nodeChild.getNodeType() == null) { + nodeChild.addError("No valid node type could be resoleved."); + } if (nodeChild.hasErrors()) { continue; } @@ -541,153 +401,182 @@ return filteredChildren; } - private void parseMethods(final NodeData node, List elements) { - node.setShortCircuits(new ShortCircuitParser(context, node).parse(elements)); - node.setSpecializationListeners(new SpecializationListenerParser(context, node).parse(elements)); - List generics = new GenericParser(context, node).parse(elements); - List specializations = new SpecializationMethodParser(context, node).parse(elements); - node.setCasts(new CreateCastParser(context, node).parse(elements)); + private List parseExecutions(List children, List elements) { + if (children == null) { + return null; + } + + // pre-parse short circuits + Set shortCircuits = new HashSet<>(); + List methods = ElementFilter.methodsIn(elements); + for (ExecutableElement method : methods) { + AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class); + if (mirror != null) { + shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value")); + } + } + + boolean hasVarArgs = false; + int maxSignatureSize = 0; + if (!children.isEmpty()) { + int lastIndex = children.size() - 1; + hasVarArgs = children.get(lastIndex).getCardinality() == Cardinality.MANY; + if (hasVarArgs) { + maxSignatureSize = lastIndex; + } else { + maxSignatureSize = children.size(); + } + } + + // pre-parse specializations + for (ExecutableElement method : methods) { + AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, Specialization.class); + if (mirror == null) { + continue; + } - List allSpecializations = new ArrayList<>(); - allSpecializations.addAll(generics); - allSpecializations.addAll(specializations); + int currentArgumentCount = 0; + boolean skipShortCircuit = false; + for (VariableElement var : method.getParameters()) { + TypeMirror type = var.asType(); + if (currentArgumentCount == 0) { + // skip optionals + if (Utils.typeEquals(type, context.getTruffleTypes().getFrame())) { + continue; + } + // TODO skip optional fields? + } + int childIndex = currentArgumentCount < children.size() ? currentArgumentCount : children.size() - 1; + if (childIndex == -1) { + continue; + } + if (!skipShortCircuit) { + NodeChildData child = children.get(childIndex); + if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentCount - childIndex))) { + skipShortCircuit = true; + continue; + } + } else { + skipShortCircuit = false; + } - node.setSpecializations(allSpecializations); + currentArgumentCount++; + } + maxSignatureSize = Math.max(maxSignatureSize, currentArgumentCount); + } + + List executions = new ArrayList<>(); + for (int i = 0; i < maxSignatureSize; i++) { + int childIndex = i; + boolean varArg = false; + if (childIndex >= children.size() - 1) { + if (hasVarArgs) { + childIndex = children.size() - 1; + varArg = hasVarArgs; + } else if (childIndex >= children.size()) { + break; + } + } + int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1; + NodeChildData child = children.get(childIndex); + boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, varArgsIndex)); + executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit)); + } + return executions; } - private static List splitNodeData(NodeData node) { - SortedMap> groupedSpecializations = groupByNodeId(node.getSpecializations()); - SortedMap> groupedListeners = groupByNodeId(node.getSpecializationListeners()); - SortedMap> groupedCasts = groupByNodeId(node.getCasts()); - - Set ids = new TreeSet<>(); - ids.addAll(groupedSpecializations.keySet()); - ids.addAll(groupedListeners.keySet()); + private static Map> groupExecutableTypes(List executableTypes) { + Map> groupedTypes = new TreeMap<>(); + for (ExecutableTypeData type : executableTypes) { + int evaluatedCount = type.getEvaluatedCount(); - List splitted = new ArrayList<>(); - for (String id : ids) { - List specializations = groupedSpecializations.get(id); - List listeners = groupedListeners.get(id); - List casts = groupedCasts.get(id); - - if (specializations == null) { - specializations = new ArrayList<>(); + List types = groupedTypes.get(evaluatedCount); + if (types == null) { + types = new ArrayList<>(); + groupedTypes.put(evaluatedCount, types); } - - if (listeners == null) { - listeners = new ArrayList<>(); - } - - String nodeId = node.getNodeId(); - if (nodeId.endsWith("Node") && !nodeId.equals("Node")) { - nodeId = nodeId.substring(0, nodeId.length() - 4); - } - String newNodeId = nodeId + Utils.firstLetterUpperCase(id); - NodeData copy = new NodeData(node, id, newNodeId); - - copy.setSpecializations(specializations); - copy.setSpecializationListeners(listeners); - copy.setCasts(casts); - - splitted.add(copy); + types.add(type); } - node.setSpecializations(new ArrayList()); - node.setSpecializationListeners(new ArrayList()); - node.setCasts(new ArrayList()); - - return splitted; + for (List types : groupedTypes.values()) { + Collections.sort(types); + } + return groupedTypes; } - private void finalizeSpecializations(List elements, final NodeData node) { - List specializations = new ArrayList<>(node.getSpecializations()); + private void initializeChildren(NodeData node) { + for (NodeChildData nodeChild : node.getChildren()) { + NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(nodeChild.getNodeType())); + nodeChild.setNode(fieldNodeData); + if (fieldNodeData == null) { + nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(nodeChild.getNodeType())); + } else if (!Utils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) { + nodeChild.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(), + NodeChild.class.getSimpleName(), Utils.getSimpleName(node.getTypeSystem().getTemplateType()), Utils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType())); + } + if (fieldNodeData != null) { + List types = nodeChild.findGenericExecutableTypes(context); + if (types.isEmpty()) { + AnnotationValue executeWithValue = Utils.getAnnotationValue(nodeChild.getMessageAnnotation(), "executeWith"); + nodeChild.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", nodeChild.getExecuteWith().size(), + Utils.getSimpleName(nodeChild.getNodeType())); + } + } + } + } - if (specializations.isEmpty()) { + private void initializeSpecializations(List elements, final NodeData node) { + if (node.getSpecializations().isEmpty()) { return; } - for (SpecializationData specialization : specializations) { - matchGuards(elements, specialization); - } - - List generics = new ArrayList<>(); - for (SpecializationData spec : specializations) { - if (spec.isGeneric()) { - generics.add(spec); + for (SpecializationData specialization : node.getSpecializations()) { + if (!specialization.isSpecialized()) { + continue; } - } - - if (generics.size() == 1 && specializations.size() == 1) { - for (SpecializationData generic : generics) { - generic.addError("@%s defined but no @%s.", Generic.class.getSimpleName(), Specialization.class.getSimpleName()); - } - } - - SpecializationData genericSpecialization = null; - if (generics.size() > 1) { - for (SpecializationData generic : generics) { - generic.addError("Only @%s is allowed per operation.", Generic.class.getSimpleName()); - } - return; - } else if (generics.size() == 1) { - genericSpecialization = generics.get(0); - } else if (node.needsRewrites(context)) { - genericSpecialization = createGenericSpecialization(node, specializations); - specializations.add(genericSpecialization); + initializeGuards(elements, specialization); } - if (genericSpecialization != null) { - for (ActualParameter parameter : genericSpecialization.getReturnTypeAndParameters()) { - 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.getType())); - } - } - if (types.size() > 1) { - genericSpecialization.replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, node.getTypeSystem().getGenericTypeData())); - } - } - TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", node, genericSpecialization.getSpecification(), null, null, genericSpecialization.getReturnType(), - genericSpecialization.getParameters()); - // should not use messages from generic specialization - uninializedMethod.getMessages().clear(); - specializations.add(new SpecializationData(uninializedMethod, false, true, false)); + initializeGeneric(node); + initializeUninitialized(node); + initializePolymorphism(node); // requires specializations + Collections.sort(node.getSpecializations()); + initializeReachability(node); + + // reduce polymorphicness if generic is not reachable + if (node.getGenericSpecialization() != null && !node.getGenericSpecialization().isReachable()) { + node.setPolymorphicDepth(1); + node.getSpecializations().remove(node.getPolymorphicSpecialization()); } - Collections.sort(specializations); - - node.setSpecializations(specializations); - List needsId = new ArrayList<>(); - for (SpecializationData specialization : specializations) { + for (SpecializationData specialization : node.getSpecializations()) { if (specialization.isGeneric()) { specialization.setId("Generic"); } else if (specialization.isUninitialized()) { specialization.setId("Uninitialized"); + } else if (specialization.isPolymorphic()) { + specialization.setId("Polymorphic"); + } else if (specialization.isSpecialized()) { + needsId.add(specialization); } else { - needsId.add(specialization); + throw new AssertionError(); } } // 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)); - } + List ids = initializeSpecializationIds(needsId); + for (int i = 0; i < ids.size(); i++) { + needsId.get(i).setId(ids.get(i)); } - // calculate reachability + } + + private void initializeReachability(final NodeData node) { SpecializationData prev = null; - int polymorphicCombinations = 0; boolean reachable = true; - for (SpecializationData specialization : specializations) { - if (specialization.isUninitialized()) { + for (SpecializationData specialization : node.getSpecializations()) { + if (specialization.isUninitialized() || specialization.isPolymorphic()) { specialization.setReachable(true); continue; } @@ -700,204 +589,21 @@ if (!specialization.hasRewrite(context)) { reachable = false; } - if (!specialization.isGeneric()) { - int combinations = 1; - for (ActualParameter parameter : specialization.getParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - TypeData type = parameter.getTypeSystemType(); - combinations *= node.getTypeSystem().lookupSourceTypes(type).size(); - } - polymorphicCombinations += combinations; - } - prev = specialization; } - - // initialize polymorphic depth - if (node.getPolymorphicDepth() < 0) { - node.setPolymorphicDepth(polymorphicCombinations - 1); - } - - // reduce polymorphicness if generic is not reachable - if (node.getGenericSpecialization() != null && !node.getGenericSpecialization().isReachable()) { - node.setPolymorphicDepth(1); - } } - private SpecializationData createGenericSpecialization(final NodeData node, List specializations) { - SpecializationData genericSpecialization; - SpecializationData specialization = specializations.get(0); - GenericParser parser = new GenericParser(context, node); - MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null); - - List parameters = new ArrayList<>(); - for (ActualParameter parameter : specialization.getReturnTypeAndParameters()) { - if (!parameter.getSpecification().isSignature()) { - parameters.add(new ActualParameter(parameter)); - continue; - } - NodeData childNode = node; - NodeChildData child = node.findChild(parameter.getSpecification().getName()); - if (child != null) { - childNode = child.getNodeData(); - } - - TypeData genericType = null; - - Set types = new HashSet<>(); - for (SpecializationData otherSpecialization : specializations) { - ActualParameter otherParameter = otherSpecialization.findParameter(parameter.getLocalName()); - if (otherParameter != null) { - types.add(otherParameter.getTypeSystemType()); - } - } - - assert !types.isEmpty(); - - if (types.size() == 1) { - ExecutableTypeData executable = childNode.findExecutableType(types.iterator().next(), 0); - if (executable != null && !executable.hasUnexpectedValue(context)) { - genericType = types.iterator().next(); - } else { - genericType = childNode.findAnyGenericExecutableType(context, 0).getType(); - } - } else { - genericType = childNode.findAnyGenericExecutableType(context, 0).getType(); - } - - parameters.add(new ActualParameter(parameter, genericType)); - } - ActualParameter returnType = parameters.get(0); - parameters = parameters.subList(1, parameters.size()); - - TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters); - genericSpecialization = new SpecializationData(genericMethod, true, false, false); - return genericSpecialization; - } - - private void assignShortCircuitsToSpecializations(NodeData node) { - Map> groupedShortCircuits = groupShortCircuits(node.getShortCircuits()); - - boolean valid = true; - for (NodeChildData field : node.filterFields(ExecutionKind.SHORT_CIRCUIT)) { - String valueName = field.getName(); - List availableCircuits = groupedShortCircuits.get(valueName); - - if (availableCircuits == null || availableCircuits.isEmpty()) { - node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName); - valid = false; - continue; - } - - boolean sameMethodName = true; - String methodName = availableCircuits.get(0).getMethodName(); - for (ShortCircuitData circuit : availableCircuits) { - if (!circuit.getMethodName().equals(methodName)) { - sameMethodName = false; - } - } - - if (!sameMethodName) { - for (ShortCircuitData circuit : availableCircuits) { - circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName); - } - valid = false; - continue; - } - - ShortCircuitData genericCircuit = null; - for (ShortCircuitData circuit : availableCircuits) { - if (isGenericShortCutMethod(node, circuit)) { - genericCircuit = circuit; - break; - } - } - - if (genericCircuit == null) { - node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName); - valid = false; - continue; - } - - for (ShortCircuitData circuit : availableCircuits) { - if (circuit != genericCircuit) { - circuit.setGenericShortCircuitMethod(genericCircuit); - } - } - } - - if (!valid) { - return; - } - - NodeChildData[] fields = node.filterFields(ExecutionKind.SHORT_CIRCUIT); - List specializations = new ArrayList<>(); - specializations.addAll(node.getSpecializations()); - specializations.addAll(node.getPolymorphicSpecializations()); - - for (SpecializationData specialization : specializations) { - List assignedShortCuts = new ArrayList<>(fields.length); - - for (int i = 0; i < fields.length; i++) { - List availableShortCuts = groupedShortCircuits.get(fields[i].getName()); - - ShortCircuitData genericShortCircuit = null; - ShortCircuitData compatibleShortCircuit = null; - for (ShortCircuitData circuit : availableShortCuts) { - if (circuit.isGeneric()) { - genericShortCircuit = circuit; - } else if (circuit.isCompatibleTo(specialization)) { - compatibleShortCircuit = circuit; - } - } - - if (compatibleShortCircuit == null) { - compatibleShortCircuit = genericShortCircuit; - } - assignedShortCuts.add(compatibleShortCircuit); - } - specialization.setShortCircuits(assignedShortCuts); - } - } - - private void matchGuards(List elements, SpecializationData specialization) { - if (specialization.getGuardDefinitions().isEmpty()) { - specialization.setGuards(Collections. emptyList()); - return; - } - - List foundGuards = new ArrayList<>(); - List methods = ElementFilter.methodsIn(elements); - for (String guardDefinition : specialization.getGuardDefinitions()) { - GuardParser parser = new GuardParser(context, specialization, guardDefinition); - List guards = parser.parse(methods); - if (!guards.isEmpty()) { - foundGuards.add(guards.get(0)); - } else { - // error no guard found - MethodSpec spec = parser.createSpecification(specialization.getMethod(), null); - spec.applyTypeDefinitions("types"); - specialization.addError("Guard with method name '%s' not found. Expected signature: %n%s", guardDefinition, spec.toSignatureString("guard")); - } - } - - specialization.setGuards(foundGuards); - - } - - private static List calculateSpecializationIds(List specializations) { + private static List initializeSpecializationIds(List specializations) { int lastSize = -1; List> signatureChunks = new ArrayList<>(); for (SpecializationData other : specializations) { - if (other.isUninitialized() || other.isGeneric()) { + if (!other.isSpecialized()) { continue; } List paramIds = new LinkedList<>(); paramIds.add(Utils.getTypeId(other.getReturnType().getType())); for (ActualParameter param : other.getParameters()) { - if (other.getNode().findChild(param.getSpecification().getName()) == null) { + if (param.getSpecification().getExecution() == null) { continue; } paramIds.add(Utils.getTypeId(param.getType())); @@ -999,25 +705,370 @@ return signatures; } - private void verifyNode(NodeData nodeData, List elements) { - // verify order is not ambiguous - verifySpecializationOrder(nodeData); + private void initializeGuards(List elements, SpecializationData specialization) { + if (specialization.getGuardDefinitions().isEmpty()) { + specialization.setGuards(Collections. emptyList()); + return; + } + + List foundGuards = new ArrayList<>(); + List methods = ElementFilter.methodsIn(elements); + for (String guardDefinition : specialization.getGuardDefinitions()) { + GuardParser parser = new GuardParser(context, specialization, guardDefinition); + List guards = parser.parse(methods); + if (!guards.isEmpty()) { + foundGuards.add(guards.get(0)); + } else { + // error no guard found + MethodSpec spec = parser.createSpecification(specialization.getMethod(), null); + spec.applyTypeDefinitions("types"); + specialization.addError("Guard with method name '%s' not found. Expected signature: %n%s", guardDefinition, spec.toSignatureString("guard")); + } + } + + specialization.setGuards(foundGuards); + + } + + private void initializeGeneric(final NodeData node) { + if (!node.needsRewrites(context)) { + return; + } - verifyMissingAbstractMethods(nodeData, elements); + List generics = new ArrayList<>(); + for (SpecializationData spec : node.getSpecializations()) { + if (spec.isGeneric()) { + generics.add(spec); + } + } + + if (generics.size() == 1 && node.getSpecializations().size() == 1) { + // TODO this limitation should be lifted + for (SpecializationData generic : generics) { + generic.addError("@%s defined but no @%s.", Generic.class.getSimpleName(), Specialization.class.getSimpleName()); + } + } + + if (generics.isEmpty()) { + node.getSpecializations().add(createGenericSpecialization(node)); + } else { + if (generics.size() > 1) { + for (SpecializationData generic : generics) { + generic.addError("Only @%s is allowed per operation.", Generic.class.getSimpleName()); + } + } + } + } + + private SpecializationData createGenericSpecialization(final NodeData node) { + SpecializationData specialization = node.getSpecializations().get(0); + GenericParser parser = new GenericParser(context, node); + MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null); + specification.getImplicitRequiredTypes().clear(); + + List parameterTypes = new ArrayList<>(); + int signatureIndex = 1; + for (ParameterSpec spec : specification.getRequired()) { + parameterTypes.add(createGenericType(spec, node.getSpecializations(), signatureIndex)); + if (spec.isSignature()) { + signatureIndex++; + } + } + TypeMirror returnType = createGenericType(specification.getReturnType(), node.getSpecializations(), 0); + return parser.create("Generic", null, null, returnType, parameterTypes); + } - verifyConstructors(nodeData); + private TypeMirror createGenericType(ParameterSpec spec, List specializations, int signatureIndex) { + NodeExecutionData execution = spec.getExecution(); + if (execution == null) { + if (spec.getAllowedTypes().size() == 1) { + return spec.getAllowedTypes().get(0); + } else { + return Utils.getCommonSuperType(context, spec.getAllowedTypes().toArray(new TypeMirror[0])); + } + } else { + Set types = new HashSet<>(); + for (SpecializationData specialization : specializations) { + types.add(specialization.getTypeSignature().get(signatureIndex)); + } + + NodeChildData child = execution.getChild(); + + TypeData genericType = null; + if (types.size() == 1) { + ExecutableTypeData executable = child.findExecutableType(context, types.iterator().next()); + if (executable != null && !executable.hasUnexpectedValue(context)) { + genericType = types.iterator().next(); + } + } + if (genericType == null) { + genericType = child.findAnyGenericExecutableType(context).getType(); + } + return genericType.getPrimitiveType(); + } + } - verifyNamingConvention(nodeData.getShortCircuits(), "needs"); + private static void initializeUninitialized(final NodeData node) { + SpecializationData generic = node.getGenericSpecialization(); + if (generic == null) { + return; + } + for (ActualParameter parameter : generic.getReturnTypeAndParameters()) { + if (Utils.isObject(parameter.getType())) { + continue; + } + Set types = new HashSet<>(); + for (SpecializationData specialization : node.getSpecializations()) { + ActualParameter actualParameter = specialization.findParameter(parameter.getLocalName()); + if (actualParameter != null) { + types.add(Utils.getQualifiedName(actualParameter.getType())); + } + } + if (types.size() > 1) { + generic.replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, node.getTypeSystem().getGenericTypeData())); + } + } + TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", node, generic.getSpecification(), null, null, generic.getReturnType(), generic.getParameters()); + // should not use messages from generic specialization + uninializedMethod.getMessages().clear(); + node.getSpecializations().add(new SpecializationData(node, uninializedMethod, SpecializationKind.UNINITIALIZED)); + } + + private void initializePolymorphism(NodeData node) { + initializePolymorphicDepth(node); + + if (!node.needsRewrites(context) || !node.isPolymorphic()) { + return; + } - verifySpecializationThrows(nodeData); + SpecializationData generic = node.getGenericSpecialization(); + + List polymorphicSignature = new ArrayList<>(); + List updatePolymorphic = Arrays.asList(); + for (ActualParameter genericParameter : updatePolymorphic) { + if (!genericParameter.getSpecification().isSignature()) { + continue; + } + + Set usedTypes = new HashSet<>(); + for (SpecializationData specialization : node.getSpecializations()) { + if (!specialization.isSpecialized()) { + continue; + } + ActualParameter parameter = specialization.findParameter(genericParameter.getLocalName()); + if (parameter == null) { + throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName()); + } + usedTypes.add(parameter.getTypeSystemType()); + } + + TypeData polymorphicType; + if (usedTypes.size() == 1) { + polymorphicType = usedTypes.iterator().next(); + } else { + polymorphicType = node.getTypeSystem().getGenericTypeData(); + } + polymorphicSignature.add(polymorphicType); + } + + SpecializationData polymorphic = new SpecializationData(node, generic, SpecializationKind.POLYMORPHIC); + polymorphic.updateSignature(new TypeSignature(polymorphicSignature)); + node.getSpecializations().add(polymorphic); } - private static void verifyNodeChild(NodeChildData nodeChild) { - if (nodeChild.getNodeType() == null) { - nodeChild.addError("No valid node type could be resoleved."); + private static void initializePolymorphicDepth(final NodeData node) { + int polymorphicCombinations = 0; + for (SpecializationData specialization : node.getSpecializations()) { + if (specialization.isGeneric()) { + continue; + } + + int combinations = 1; + for (ActualParameter parameter : specialization.getSignatureParameters()) { + combinations *= node.getTypeSystem().lookupSourceTypes(parameter.getTypeSystemType()).size(); + } + polymorphicCombinations += combinations; + } + + // initialize polymorphic depth + if (node.getPolymorphicDepth() < 0) { + node.setPolymorphicDepth(polymorphicCombinations - 1); + } + + } + + private void initializeShortCircuits(NodeData node) { + Map> groupedShortCircuits = groupShortCircuits(node.getShortCircuits()); + + boolean valid = true; + List shortCircuitExecutions = new ArrayList<>(); + for (NodeExecutionData execution : node.getChildExecutions()) { + if (!execution.isShortCircuit()) { + continue; + } + shortCircuitExecutions.add(execution); + String valueName = execution.getShortCircuitId(); + List availableCircuits = groupedShortCircuits.get(valueName); + + if (availableCircuits == null || availableCircuits.isEmpty()) { + node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName); + valid = false; + continue; + } + + boolean sameMethodName = true; + String methodName = availableCircuits.get(0).getMethodName(); + for (ShortCircuitData circuit : availableCircuits) { + if (!circuit.getMethodName().equals(methodName)) { + sameMethodName = false; + } + } + + if (!sameMethodName) { + for (ShortCircuitData circuit : availableCircuits) { + circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName); + } + valid = false; + continue; + } + + ShortCircuitData genericCircuit = null; + for (ShortCircuitData circuit : availableCircuits) { + if (isGenericShortCutMethod(circuit)) { + genericCircuit = circuit; + break; + } + } + + if (genericCircuit == null) { + node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName); + valid = false; + continue; + } + + for (ShortCircuitData circuit : availableCircuits) { + if (circuit != genericCircuit) { + circuit.setGenericShortCircuitMethod(genericCircuit); + } + } + } + + if (!valid) { + return; } - // FIXME verify node child - // FIXME verify node type set + + List specializations = new ArrayList<>(); + specializations.addAll(node.getSpecializations()); + for (SpecializationData specialization : specializations) { + List assignedShortCuts = new ArrayList<>(shortCircuitExecutions.size()); + + for (NodeExecutionData shortCircuit : shortCircuitExecutions) { + List availableShortCuts = groupedShortCircuits.get(shortCircuit.getShortCircuitId()); + + ShortCircuitData genericShortCircuit = null; + ShortCircuitData compatibleShortCircuit = null; + for (ShortCircuitData circuit : availableShortCuts) { + if (circuit.isGeneric()) { + genericShortCircuit = circuit; + } else if (circuit.isCompatibleTo(specialization)) { + compatibleShortCircuit = circuit; + } + } + + if (compatibleShortCircuit == null) { + compatibleShortCircuit = genericShortCircuit; + } + assignedShortCuts.add(compatibleShortCircuit); + } + specialization.setShortCircuits(assignedShortCuts); + } + } + + private boolean isGenericShortCutMethod(ShortCircuitData method) { + for (ActualParameter parameter : method.getParameters()) { + NodeExecutionData execution = parameter.getSpecification().getExecution(); + if (execution == null) { + continue; + } + ExecutableTypeData found = null; + List executableElements = execution.getChild().findGenericExecutableTypes(context); + for (ExecutableTypeData executable : executableElements) { + if (executable.getType().equalsType(parameter.getTypeSystemType())) { + found = executable; + break; + } + } + if (found == null) { + return false; + } + } + return true; + } + + private static Map> groupShortCircuits(List shortCircuits) { + Map> group = new HashMap<>(); + for (ShortCircuitData shortCircuit : shortCircuits) { + List circuits = group.get(shortCircuit.getValueName()); + if (circuits == null) { + circuits = new ArrayList<>(); + group.put(shortCircuit.getValueName(), circuits); + } + circuits.add(shortCircuit); + } + return group; + } + + private static boolean verifySpecializationSameLength(NodeData nodeData) { + int lastArgs = -1; + for (SpecializationData specializationData : nodeData.getSpecializations()) { + int signatureArgs = specializationData.getSignatureSize(); + if (lastArgs == signatureArgs) { + continue; + } + if (lastArgs != -1) { + for (SpecializationData specialization : nodeData.getSpecializations()) { + specialization.addError("All specializations must have the same number of arguments."); + } + return false; + } else { + lastArgs = signatureArgs; + } + } + return true; + } + + private static void verifyVisibilities(NodeData node) { + if (node.getTemplateType().getModifiers().contains(Modifier.PRIVATE) && node.getSpecializations().size() > 0) { + node.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName()); + } + } + + private static void verifySpecializationOrder(NodeData node) { + List specializations = node.getSpecializations(); + for (int i = 0; i < specializations.size(); i++) { + SpecializationData m1 = specializations.get(i); + for (int j = i + 1; j < specializations.size(); j++) { + SpecializationData m2 = specializations.get(j); + int inferredOrder = m1.compareBySignature(m2); + + if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) { + int specOrder = m1.getOrder() - m2.getOrder(); + if (specOrder == 0) { + m1.addError("Order value %d used multiple times", m1.getOrder()); + m2.addError("Order value %d used multiple times", m1.getOrder()); + return; + } else if ((specOrder < 0 && inferredOrder > 0) || (specOrder > 0 && inferredOrder < 0)) { + m1.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); + m2.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); + return; + } + } else if (inferredOrder == 0) { + SpecializationData m = (m1.getOrder() == Specialization.DEFAULT_ORDER ? m1 : m2); + m.addError("Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this."); + return; + } + } + } } private static void verifyMissingAbstractMethods(NodeData nodeData, List originalElements) { @@ -1028,7 +1079,6 @@ } List elements = new ArrayList<>(originalElements); - Set unusedElements = new HashSet<>(elements); for (TemplateMethod method : nodeData.getAllTemplateMethods()) { unusedElements.remove(method.getMethod()); @@ -1053,6 +1103,33 @@ } } + private static void verifyNamingConvention(List methods, String prefix) { + for (int i = 0; i < methods.size(); i++) { + TemplateMethod m1 = methods.get(i); + if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) { + m1.addError("Naming convention: method name must start with '%s'.", prefix); + } + } + } + + private static void verifySpecializationThrows(NodeData node) { + Map specializationMap = new HashMap<>(); + for (SpecializationData spec : node.getSpecializations()) { + specializationMap.put(spec.getMethodName(), spec); + } + for (SpecializationData sourceSpecialization : node.getSpecializations()) { + if (sourceSpecialization.getExceptions() != null) { + for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) { + for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) { + if (otherThrowsData != throwsData && Utils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) { + throwsData.addError("Duplicate exception type."); + } + } + } + } + } + } + private void verifyConstructors(NodeData nodeData) { if (!nodeData.needsRewrites(context)) { // no specialization constructor is needed if the node never rewrites. @@ -1093,104 +1170,6 @@ return constructor.getParameters().size() == 1 && Utils.typeEquals(constructor.getParameters().get(0).asType(), context.getTruffleTypes().getSourceSection()); } - private static boolean verifySpecializationParameters(NodeData nodeData) { - boolean valid = true; - int args = -1; - for (SpecializationData specializationData : nodeData.getSpecializations()) { - int signatureArgs = 0; - for (ActualParameter param : specializationData.getParameters()) { - if (param.getSpecification().isSignature()) { - signatureArgs++; - } - } - if (args != -1 && args != signatureArgs) { - valid = false; - break; - } - args = signatureArgs; - } - if (!valid) { - for (SpecializationData specialization : nodeData.getSpecializations()) { - specialization.addError("All specializations must have the same number of arguments."); - } - } - return valid; - } - - private static void verifySpecializationOrder(NodeData node) { - List specializations = node.getSpecializations(); - for (int i = 0; i < specializations.size(); i++) { - SpecializationData m1 = specializations.get(i); - for (int j = i + 1; j < specializations.size(); j++) { - SpecializationData m2 = specializations.get(j); - int inferredOrder = m1.compareBySignature(m2); - - if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) { - int specOrder = m1.getOrder() - m2.getOrder(); - if (specOrder == 0) { - m1.addError("Order value %d used multiple times", m1.getOrder()); - m2.addError("Order value %d used multiple times", m1.getOrder()); - return; - } else if ((specOrder < 0 && inferredOrder > 0) || (specOrder > 0 && inferredOrder < 0)) { - m1.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); - m2.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); - return; - } - } else if (inferredOrder == 0) { - SpecializationData m = (m1.getOrder() == Specialization.DEFAULT_ORDER ? m1 : m2); - m.addError("Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this."); - return; - } - } - } - } - - private static void verifySpecializationThrows(NodeData node) { - Map specializationMap = new HashMap<>(); - for (SpecializationData spec : node.getSpecializations()) { - specializationMap.put(spec.getMethodName(), spec); - } - for (SpecializationData sourceSpecialization : node.getSpecializations()) { - if (sourceSpecialization.getExceptions() != null) { - for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) { - for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) { - if (otherThrowsData != throwsData && Utils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) { - throwsData.addError("Duplicate exception type."); - } - } - } - } - } - } - - private static void verifyNamingConvention(List methods, String prefix) { - for (int i = 0; i < methods.size(); i++) { - TemplateMethod m1 = methods.get(i); - if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) { - m1.addError("Naming convention: method name must start with '%s'.", prefix); - } - } - } - - private static Map> groupExecutableTypes(List executableTypes) { - Map> groupedTypes = new TreeMap<>(); - for (ExecutableTypeData type : executableTypes) { - int evaluatedCount = type.getEvaluatedCount(); - - List types = groupedTypes.get(evaluatedCount); - if (types == null) { - types = new ArrayList<>(); - groupedTypes.put(evaluatedCount, types); - } - types.add(type); - } - - for (List types : groupedTypes.values()) { - Collections.sort(types); - } - return groupedTypes; - } - private AnnotationMirror findFirstAnnotation(List elements, Class annotation) { for (Element element : elements) { AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, element, annotation); @@ -1230,61 +1209,13 @@ return null; } - private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) { - for (ActualParameter parameter : method.getParameters()) { - NodeChildData field = node.findChild(parameter.getSpecification().getName()); - if (field == null) { - continue; - } - ExecutableTypeData found = null; - List executableElements = field.findGenericExecutableTypes(context); - for (ExecutableTypeData executable : executableElements) { - if (executable.getType().equalsType(parameter.getTypeSystemType())) { - found = executable; - break; - } - } - if (found == null) { - return false; + private static List collectSuperClasses(List collection, TypeElement element) { + if (element != null) { + collection.add(element); + if (element.getSuperclass() != null) { + collectSuperClasses(collection, Utils.fromTypeMirror(element.getSuperclass())); } } - return true; - } - - private static Map> groupShortCircuits(List shortCircuits) { - Map> group = new HashMap<>(); - for (ShortCircuitData shortCircuit : shortCircuits) { - List circuits = group.get(shortCircuit.getValueName()); - if (circuits == null) { - circuits = new ArrayList<>(); - group.put(shortCircuit.getValueName(), circuits); - } - circuits.add(shortCircuit); - } - return group; - } - - private static SortedMap> groupByNodeId(List methods) { - SortedMap> grouped = new TreeMap<>(); - for (M m : methods) { - List list = grouped.get(m.getId()); - if (list == null) { - list = new ArrayList<>(); - grouped.put(m.getId(), list); - } - list.add(m); - } - return grouped; - } - - private static List findSuperClasses(List collection, TypeElement element) { - if (element.getSuperclass() != null) { - TypeElement superElement = Utils.fromTypeMirror(element.getSuperclass()); - if (superElement != null) { - findSuperClasses(collection, superElement); - } - } - collection.add(element); return collection; } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java Tue Jan 07 18:53:04 2014 +0100 @@ -29,7 +29,6 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.node.NodeChildData.*; import com.oracle.truffle.dsl.processor.template.*; public class ShortCircuitParser extends NodeMethodParser { @@ -40,15 +39,17 @@ super(context, node); shortCircuitValues = new HashSet<>(); - NodeChildData[] shortCircuitFields = node.filterFields(ExecutionKind.SHORT_CIRCUIT); - for (NodeChildData field : shortCircuitFields) { - shortCircuitValues.add(field.getName()); + for (NodeExecutionData execution : node.getChildExecutions()) { + if (execution.isShortCircuit()) { + shortCircuitValues.add(execution.getShortCircuitId()); + } } } @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { String shortCircuitValue = Utils.getAnnotationValue(String.class, mirror, "value"); + return createDefaultMethodSpec(method, mirror, true, shortCircuitValue); } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java Tue Jan 07 18:53:04 2014 +0100 @@ -33,24 +33,25 @@ public class SpecializationData extends TemplateMethod { + public enum SpecializationKind { + UNINITIALIZED, SPECIALIZED, POLYMORPHIC, GENERIC + } + + private final NodeData node; private final int order; - private final boolean generic; - private final boolean polymorphic; - private final boolean uninitialized; + private final SpecializationKind kind; private final List exceptions; private List guardDefinitions = Collections.emptyList(); private List guards = Collections.emptyList(); private List shortCircuits; private List assumptions = Collections.emptyList(); - private NodeData node; private boolean reachable; - public SpecializationData(TemplateMethod template, int order, List exceptions) { + public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind, int order, List exceptions) { super(template); + this.node = node; this.order = order; - this.generic = false; - this.uninitialized = false; - this.polymorphic = false; + this.kind = kind; this.exceptions = exceptions; for (SpecializationThrowsData exception : exceptions) { @@ -58,13 +59,8 @@ } } - public SpecializationData(TemplateMethod template, boolean generic, boolean uninitialized, boolean polymorphic) { - super(template); - this.order = Specialization.DEFAULT_ORDER; - this.generic = generic; - this.uninitialized = uninitialized; - this.polymorphic = polymorphic; - this.exceptions = Collections.emptyList(); + public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind) { + this(node, template, kind, Specialization.DEFAULT_ORDER, new ArrayList()); } public void setReachable(boolean reachable) { @@ -76,7 +72,7 @@ } public boolean isPolymorphic() { - return polymorphic; + return kind == SpecializationKind.POLYMORPHIC; } @Override @@ -99,20 +95,12 @@ return false; } - for (ActualParameter parameter : getParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - NodeChildData child = getNode().findChild(parameter.getSpecification().getName()); - if (child == null) { - continue; - } + for (ActualParameter parameter : getSignatureParameters()) { ActualParameter genericParameter = getNode().getGenericSpecialization().findParameter(parameter.getLocalName()); if (!parameter.getTypeSystemType().equals(genericParameter.getTypeSystemType())) { return false; } } - return true; } @@ -126,12 +114,8 @@ if (!getAssumptions().isEmpty()) { return true; } - for (ActualParameter parameter : getParameters()) { - NodeChildData child = getNode().findChild(parameter.getSpecification().getName()); - if (child == null) { - continue; - } - ExecutableTypeData type = child.findExecutableType(context, parameter.getTypeSystemType()); + for (ActualParameter parameter : getSignatureParameters()) { + ExecutableTypeData type = parameter.getSpecification().getExecution().getChild().findExecutableType(context, parameter.getTypeSystemType()); if (type.hasUnexpectedValue(context)) { return true; } @@ -153,12 +137,12 @@ SpecializationData m2 = (SpecializationData) other; + int kindOrder = kind.compareTo(m2.kind); + if (kindOrder != 0) { + return kindOrder; + } if (getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) { return getOrder() - m2.getOrder(); - } else if (isUninitialized() ^ m2.isUninitialized()) { - return isUninitialized() ? -1 : 1; - } else if (isGeneric() ^ m2.isGeneric()) { - return isGeneric() ? 1 : -1; } if (getTemplate() != m2.getTemplate()) { @@ -172,10 +156,6 @@ return node; } - public void setNode(NodeData node) { - this.node = node; - } - public void setGuards(List guards) { this.guards = guards; } @@ -189,15 +169,15 @@ } public boolean isSpecialized() { - return !isGeneric() && !isUninitialized() && !isPolymorphic(); + return kind == SpecializationKind.SPECIALIZED; } public boolean isGeneric() { - return generic; + return kind == SpecializationKind.GENERIC; } public boolean isUninitialized() { - return uninitialized; + return kind == SpecializationKind.UNINITIALIZED; } public List getExceptions() { @@ -254,7 +234,7 @@ @Override public String toString() { - return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getSignature()); + return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature()); } public void forceFrame(TypeMirror frameType) { @@ -267,7 +247,7 @@ } public boolean equalsGuards(SpecializationData specialization) { - if (assumptions.equals(specialization.getAssumptions()) && guards.equals(specialization.getGuards()) && getSignature().equalsParameters(specialization.getSignature())) { + if (assumptions.equals(specialization.getAssumptions()) && guards.equals(specialization.getGuards()) && getTypeSignature().equalsParameters(specialization.getTypeSignature())) { return true; } return false; @@ -281,4 +261,5 @@ } return false; } + } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java Tue Jan 07 18:53:04 2014 +0100 @@ -28,7 +28,7 @@ import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.template.*; -import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature; +import com.oracle.truffle.dsl.processor.template.TemplateMethod.TypeSignature; import com.oracle.truffle.dsl.processor.typesystem.*; /** @@ -55,7 +55,7 @@ this.specialization = data; this.assumptions.addAll(data.getAssumptions()); - Signature sig = data.getSignature(); + TypeSignature sig = data.getTypeSignature(); for (int i = 1; i < sig.size(); i++) { typeGuards.add(new TypeGuard(sig.get(i), i - 1)); } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.java Tue Jan 07 14:41:52 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * 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.dsl.processor.node; - -import java.lang.annotation.*; - -import javax.lang.model.element.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.template.*; - -public class SpecializationListenerParser extends NodeMethodParser { - - public SpecializationListenerParser(ProcessorContext context, NodeData node) { - super(context, node); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return createDefaultMethodSpec(method, mirror, true, null); - } - - @Override - protected ParameterSpec createReturnParameterSpec() { - return new ParameterSpec("void", getContext().getType(void.class)); - } - - @Override - public SpecializationListenerData create(TemplateMethod method, boolean invalid) { - return new SpecializationListenerData(method); - } - - @Override - public Class getAnnotationType() { - return SpecializationListener.class; - } - -} diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java Tue Jan 07 18:53:04 2014 +0100 @@ -30,6 +30,7 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.node.SpecializationData.SpecializationKind; import com.oracle.truffle.dsl.processor.template.*; public class SpecializationMethodParser extends NodeMethodParser { @@ -77,7 +78,7 @@ return Utils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass()); } }); - SpecializationData specialization = new SpecializationData(method, order, exceptionData); + SpecializationData specialization = new SpecializationData(getNode(), method, SpecializationKind.SPECIALIZED, order, exceptionData); List guardDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); specialization.setGuardDefinitions(guardDefs); diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java Tue Jan 07 18:53:04 2014 +0100 @@ -33,24 +33,24 @@ private TypeData typeSystemType; private TemplateMethod method; private final String localName; - private final int specificationIndex; - private final int varArgsIndex; + private final int specificationVarArgsIndex; + private final int typeVarArgsIndex; private final boolean implicit; - private final TypeMirror type; + private final TypeMirror actualType; - public ActualParameter(ParameterSpec specification, TypeMirror actualType, int specificationIndex, int varArgsIndex, boolean implicit) { + public ActualParameter(ParameterSpec specification, TypeMirror actualType, int specificationVarArgsIndex, int typeVarArgsIndex, boolean implicit) { this.specification = specification; - this.type = actualType; + this.actualType = actualType; this.typeSystemType = null; - this.specificationIndex = specificationIndex; + this.specificationVarArgsIndex = specificationVarArgsIndex; this.implicit = implicit; - String valueName = specification.getName() + "Value"; - if (specification.isIndexed()) { - valueName += specificationIndex; + String valueName = specification.getName() + "Value"; + if (specificationVarArgsIndex > -1) { + valueName += "_" + specificationVarArgsIndex; } - this.varArgsIndex = varArgsIndex; + this.typeVarArgsIndex = typeVarArgsIndex; this.localName = valueName; } @@ -60,29 +60,29 @@ } public ActualParameter(ActualParameter parameter, TypeData otherType) { - this(parameter.specification, otherType, parameter.specificationIndex, parameter.varArgsIndex, parameter.implicit); + this(parameter.specification, otherType, parameter.specificationVarArgsIndex, parameter.typeVarArgsIndex, parameter.implicit); } public ActualParameter(ActualParameter parameter) { this.specification = parameter.specification; - this.type = parameter.type; + this.actualType = parameter.actualType; this.typeSystemType = parameter.typeSystemType; - this.specificationIndex = parameter.specificationIndex; + this.specificationVarArgsIndex = parameter.specificationVarArgsIndex; this.implicit = parameter.implicit; this.localName = parameter.localName; - this.varArgsIndex = parameter.varArgsIndex; + this.typeVarArgsIndex = parameter.typeVarArgsIndex; } - public int getVarArgsIndex() { - return varArgsIndex; + public int getTypeVarArgsIndex() { + return typeVarArgsIndex; } public boolean isImplicit() { return implicit; } - public int getSpecificationIndex() { - return specificationIndex; + public int getSpecificationVarArgsIndex() { + return specificationVarArgsIndex; } public String getLocalName() { @@ -102,15 +102,15 @@ } public TypeMirror getType() { - return type; + return actualType; } public TypeData getTypeSystemType() { return typeSystemType; } - public boolean isVarArgs() { - return varArgsIndex >= 0; + public boolean isTypeVarArgs() { + return typeVarArgsIndex >= 0; } public ActualParameter getPreviousParameter() { @@ -119,6 +119,6 @@ @Override public String toString() { - return Utils.getSimpleName(type); + return Utils.getSimpleName(actualType); } } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java Tue Jan 07 18:53:04 2014 +0100 @@ -64,8 +64,8 @@ } verifyExpectedMessages(context, log, childMessages); - for (Message message : getMessages()) { - emitDefault(context, baseElement, log, message); + for (int i = getMessages().size() - 1; i >= 0; i--) { + emitDefault(context, baseElement, log, getMessages().get(i)); } for (MessageContainer sink : findChildContainers()) { diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java Tue Jan 07 18:53:04 2014 +0100 @@ -27,7 +27,6 @@ import javax.lang.model.type.*; import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.node.NodeChildData.*; public class MethodSpec { @@ -37,34 +36,36 @@ private final List optional = new ArrayList<>(); private final List required = new ArrayList<>(); - private int minimumRequiredArguments; - private boolean variableRequiredArguments; + private boolean ignoreAdditionalParameters; + private boolean ignoreAdditionalSpecifications; + private boolean variableRequiredParameters; + private List typeDefinitions; public MethodSpec(ParameterSpec returnType) { this.returnType = returnType; } - public void setMinimumRequiredArguments(int minimumRequiredArguments) { - this.minimumRequiredArguments = minimumRequiredArguments; + public void setVariableRequiredParameters(boolean variableRequiredParameters) { + this.variableRequiredParameters = variableRequiredParameters; } - public int getMinimumRequiredArguments() { - return minimumRequiredArguments; - } - - public void setVariableRequiredArguments(boolean variableArguments) { - this.variableRequiredArguments = variableArguments; - } - - public boolean isVariableRequiredArguments() { - return variableRequiredArguments; + public boolean isVariableRequiredParameters() { + return variableRequiredParameters; } public void addImplicitRequiredType(TypeMirror type) { this.implicitRequiredTypes.add(type); } + public void setIgnoreAdditionalParameters(boolean ignoreAdditionalParameter) { + this.ignoreAdditionalParameters = ignoreAdditionalParameter; + } + + public boolean isIgnoreAdditionalParameters() { + return ignoreAdditionalParameters; + } + public void addOptional(ParameterSpec spec) { optional.add(spec); } @@ -158,15 +159,18 @@ sep = ", "; } - for (ParameterSpec requiredSpec : getRequired()) { + for (int i = 0; i < getRequired().size(); i++) { + ParameterSpec requiredSpec = getRequired().get(i); b.append(sep); - if (requiredSpec.getCardinality() == Cardinality.MANY) { - b.append("{"); + + if (isVariableRequiredParameters() && i == getRequired().size() - 1) { + b.append(("{")); } b.append(createTypeSignature(requiredSpec, false)); - if (requiredSpec.getCardinality() == Cardinality.MANY) { - b.append("}"); + if (isVariableRequiredParameters() && i == getRequired().size() - 1) { + b.append(("}")); } + sep = ", "; } @@ -234,4 +238,12 @@ } } + public void setIgnoreAdditionalSpecifications(boolean ignoreAdditoinalSpecifications) { + this.ignoreAdditionalSpecifications = ignoreAdditoinalSpecifications; + } + + public boolean isIgnoreAdditionalSpecifications() { + return ignoreAdditionalSpecifications; + } + } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java Tue Jan 07 18:53:04 2014 +0100 @@ -27,44 +27,46 @@ import javax.lang.model.type.*; import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.node.NodeChildData.*; -import com.oracle.truffle.dsl.processor.template.MethodSpec.*; +import com.oracle.truffle.dsl.processor.node.*; +import com.oracle.truffle.dsl.processor.template.MethodSpec.TypeDef; public class ParameterSpec { private final String name; private final List allowedTypes; - /** Cardinality one or multiple. */ - private Cardinality cardinality = Cardinality.ONE; - /** Type is part of the method signature. Relevant for comparisons. */ - private boolean signature; - /** Type must be indexed when parsing. */ - private boolean indexed; /** Type is bound to local final variable. */ private boolean local; + /** Optional bound execution of node. */ + private NodeExecutionData execution; private TypeDef typeDefinition; - public ParameterSpec(String name, TypeMirror... allowedTypes) { - this(name, Arrays.asList(allowedTypes)); - } - public ParameterSpec(String name, List allowedTypes) { this.name = name; this.allowedTypes = allowedTypes; } + public ParameterSpec(String name, TypeMirror type) { + this(name, Arrays.asList(type)); + } + public ParameterSpec(ParameterSpec o, List allowedTypes) { this.name = o.name; - this.cardinality = o.cardinality; - this.signature = o.signature; - this.indexed = o.indexed; this.local = o.local; this.typeDefinition = o.typeDefinition; + this.execution = o.execution; this.allowedTypes = allowedTypes; } + public NodeExecutionData getExecution() { + return execution; + } + + public void setExecution(NodeExecutionData executionData) { + this.execution = executionData; + } + void setTypeDefinition(TypeDef typeDefinition) { this.typeDefinition = typeDefinition; } @@ -73,42 +75,22 @@ return typeDefinition; } - public void setSignature(boolean signature) { - this.signature = signature; - } - public void setLocal(boolean local) { this.local = local; } public boolean isSignature() { - return signature; + return execution != null; } public boolean isLocal() { return local; } - public boolean isIndexed() { - return indexed; - } - - public void setIndexed(boolean indexed) { - this.indexed = indexed; - } - - public void setCardinality(Cardinality cardinality) { - this.cardinality = cardinality; - } - public String getName() { return name; } - public Cardinality getCardinality() { - return cardinality; - } - public List getAllowedTypes() { return allowedTypes; } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java Tue Jan 07 18:53:04 2014 +0100 @@ -29,6 +29,7 @@ import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.typesystem.*; +import com.oracle.truffle.dsl.processor.util.*; /** * Note: this class has a natural ordering that is inconsistent with equals. @@ -133,6 +134,14 @@ return requiredParameters; } + public Iterable getSignatureParameters() { + return new FilteredIterable<>(getParameters(), new Predicate() { + public boolean evaluate(ActualParameter value) { + return value.getSpecification().isSignature(); + } + }); + } + public List getParameters() { return parameters; } @@ -202,23 +211,19 @@ return prev; } + @SuppressWarnings("unused") public int getSignatureSize() { int signatureSize = 0; - for (ActualParameter parameter : getParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } + for (ActualParameter parameter : getSignatureParameters()) { signatureSize++; } return signatureSize; } - public Signature getSignature() { - Signature signature = new Signature(); - for (ActualParameter parameter : getReturnTypeAndParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } + public TypeSignature getTypeSignature() { + TypeSignature signature = new TypeSignature(); + signature.types.add(getReturnType().getTypeSystemType()); + for (ActualParameter parameter : getSignatureParameters()) { TypeData typeData = parameter.getTypeSystemType(); if (typeData != null) { signature.types.add(typeData); @@ -241,7 +246,7 @@ return null; } - public void updateSignature(Signature signature) { + public void updateSignature(TypeSignature signature) { // TODO(CH): fails in normal usage - output ok though // assert signature.size() >= 1; @@ -299,8 +304,8 @@ throw new IllegalStateException("Cannot compare two methods with different type systems."); } - List signature1 = getSignatureTypes(getReturnTypeAndParameters()); - List signature2 = getSignatureTypes(compareMethod.getReturnTypeAndParameters()); + List signature1 = getSignatureTypes(this); + List signature2 = getSignatureTypes(compareMethod); if (signature1.size() != signature2.size()) { return signature2.size() - signature1.size(); } @@ -349,25 +354,24 @@ return Utils.getSimpleName(signature1).compareTo(Utils.getSimpleName(signature2)); } - public static List getSignatureTypes(List params) { + public static List getSignatureTypes(TemplateMethod method) { List types = new ArrayList<>(); - for (ActualParameter param : params) { - if (param.getSpecification().isSignature()) { - types.add(param.getType()); - } + types.add(method.getReturnType().getType()); + for (ActualParameter param : method.getSignatureParameters()) { + types.add(param.getType()); } return types; } - public static class Signature implements Iterable, Comparable { + public static class TypeSignature implements Iterable, Comparable { final List types; - public Signature() { + public TypeSignature() { this.types = new ArrayList<>(); } - public Signature(List signature) { + public TypeSignature(List signature) { this.types = signature; } @@ -384,7 +388,7 @@ return types.get(index); } - public int compareTo(Signature other) { + public int compareTo(TypeSignature other) { if (this == other) { return 0; } else if (types.size() != other.types.size()) { @@ -406,7 +410,7 @@ return 0; } - public Signature combine(Signature genericSignature, Signature other) { + public TypeSignature combine(TypeSignature genericSignature, TypeSignature other) { assert types.size() == other.types.size(); assert genericSignature.types.size() == other.types.size(); @@ -414,7 +418,7 @@ return this; } - Signature signature = new Signature(); + TypeSignature signature = new TypeSignature(); for (int i = 0; i < types.size(); i++) { TypeData type1 = types.get(i); TypeData type2 = other.types.get(i); @@ -427,7 +431,7 @@ return signature; } - public boolean equalsParameters(Signature other) { + public boolean equalsParameters(TypeSignature other) { if (size() != other.size()) { return false; } @@ -436,8 +440,8 @@ @Override public boolean equals(Object obj) { - if (obj instanceof Signature) { - return ((Signature) obj).types.equals(types); + if (obj instanceof TypeSignature) { + return ((TypeSignature) obj).types.equals(types); } return super.equals(obj); } @@ -451,7 +455,7 @@ return types.toString(); } - public boolean hasAnyParameterMatch(Signature other) { + public boolean hasAnyParameterMatch(TypeSignature other) { for (int i = 1; i < types.size(); i++) { TypeData type1 = types.get(i); TypeData type2 = other.types.get(i); @@ -462,7 +466,7 @@ return false; } - public boolean isCompatibleTo(Signature signature) { + public boolean isCompatibleTo(TypeSignature signature) { if (size() != signature.size()) { return false; } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java Tue Jan 07 18:53:04 2014 +0100 @@ -31,9 +31,7 @@ import javax.lang.model.type.*; import javax.lang.model.util.*; -import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.node.NodeChildData.*; import com.oracle.truffle.dsl.processor.typesystem.*; public abstract class TemplateMethodParser { @@ -142,19 +140,23 @@ methodSpecification.applyTypeDefinitions("types"); String id = method.getSimpleName().toString(); - AnnotationMirror idAnnotation = Utils.findAnnotationMirror(context.getEnvironment(), method, NodeId.class); - if (idAnnotation != null) { - id = Utils.getAnnotationValue(String.class, idAnnotation, "value"); + TypeMirror returnType = method.getReturnType(); + List parameterTypes = new ArrayList<>(); + for (VariableElement var : method.getParameters()) { + parameterTypes.add(var.asType()); } - ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); + return parseImpl(methodSpecification, id, method, annotation, returnType, parameterTypes); + } - ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, -1, false); + private E parseImpl(MethodSpec methodSpecification, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType, List parameterTypes) { + ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); + ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, template, -1, -1, false); if (returnTypeMirror == null) { if (emitErrors) { E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList()), true); String expectedReturnType = returnTypeSpec.toSignatureString(true); - String actualReturnType = Utils.getSimpleName(method.getReturnType()); + String actualReturnType = Utils.getSimpleName(returnType); String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType, methodSpecification.toSignatureString(method.getSimpleName().toString())); @@ -165,12 +167,7 @@ } } - List parameterTypes = new ArrayList<>(); - for (VariableElement var : method.getParameters()) { - parameterTypes.add(var.asType()); - } - - List parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method.isVarArgs()); + List parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method != null ? method.isVarArgs() : false); if (parameters == null) { if (isEmitErrors()) { E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList()), true); @@ -207,34 +204,31 @@ * Parameter parsing tries to parse required arguments starting from offset 0 with increasing * offset until it finds a signature end that matches the required specification. If there is no * end matching the required arguments, parsing fails. Parameters prior to the parsed required - * ones are cut and used to parse the optional parameters. All those remaining parameters must - * be consumed otherwise its an error. + * ones are cut and used to parse the optional parameters. */ private List parseParameters(MethodSpec spec, List parameterTypes, boolean varArgs) { List implicitTypes = spec.getImplicitRequiredTypes(); - int offset = -1; List parsedRequired = null; - ConsumableListIterator types = null; - while (parsedRequired == null && offset < parameterTypes.size()) { - offset++; - types = new ConsumableListIterator<>(new ArrayList<>(implicitTypes)); - types.data.addAll(parameterTypes.subList(offset, parameterTypes.size())); - parsedRequired = parseParametersRequired(spec, types, varArgs); + int offset = 0; + for (; offset <= parameterTypes.size(); offset++) { + List parameters = new ArrayList<>(implicitTypes); + parameters.addAll(parameterTypes.subList(offset, parameterTypes.size())); + parsedRequired = parseParametersRequired(spec, parameters, varArgs); + if (parsedRequired != null) { + break; + } } - if (parsedRequired == null && offset >= 0) { + if (parsedRequired == null) { return null; } - List potentialOptionals; - if (offset == -1) { - potentialOptionals = parameterTypes; - } else { - potentialOptionals = parameterTypes.subList(0, offset); + if (parsedRequired.isEmpty() && offset == 0) { + offset = parameterTypes.size(); } - types = new ConsumableListIterator<>(potentialOptionals); - List parsedOptionals = parseParametersOptional(spec, types); + List potentialOptionals = parameterTypes.subList(0, offset); + List parsedOptionals = parseParametersOptional(spec, potentialOptionals); if (parsedOptionals == null) { return null; } @@ -245,99 +239,105 @@ return finalParameters; } - private List parseParametersOptional(MethodSpec spec, ConsumableListIterator types) { + private List parseParametersOptional(MethodSpec spec, List types) { List parsedParams = new ArrayList<>(); - // parse optional parameters - ConsumableListIterator optionals = new ConsumableListIterator<>(spec.getOptional()); - for (TypeMirror type : types) { - int oldIndex = types.getIndex(); - int optionalCount = 1; - for (ParameterSpec paramspec : optionals) { - ActualParameter optionalParam = matchParameter(paramspec, type, template, 0, -1, false); + + int typeStartIndex = 0; + List specifications = spec.getOptional(); + outer: for (int specIndex = 0; specIndex < specifications.size(); specIndex++) { + ParameterSpec specification = specifications.get(specIndex); + for (int typeIndex = typeStartIndex; typeIndex < types.size(); typeIndex++) { + TypeMirror actualType = types.get(typeIndex); + ActualParameter optionalParam = matchParameter(specification, actualType, template, -1, -1, false); if (optionalParam != null) { - optionals.consume(optionalCount); - types.consume(); parsedParams.add(optionalParam); - break; + typeStartIndex = typeIndex + 1; + continue outer; } - optionalCount++; - } - if (oldIndex == types.getIndex()) { - // nothing found anymore skip optional - break; } } - if (types.getIndex() <= types.data.size() - 1) { + + if (typeStartIndex < types.size()) { + // not enough types found return null; } return parsedParams; } - private List parseParametersRequired(MethodSpec spec, ConsumableListIterator types, boolean varArgs) { + private List parseParametersRequired(MethodSpec spec, List types, boolean typeVarArgs) { List parsedParams = new ArrayList<>(); + List specifications = spec.getRequired(); + boolean specVarArgs = spec.isVariableRequiredParameters(); + int typeIndex = 0; + int specificationIndex = 0; - int varArgsParameterIndex = -1; - int specificationParameterIndex = 0; - 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.MANY) { - required.consume(); - specificationParameterIndex = 0; - continue; + ParameterSpec specification; + while ((specification = nextSpecification(specifications, specificationIndex, specVarArgs)) != null) { + TypeMirror actualType = nextActualType(types, typeIndex, typeVarArgs); + if (actualType == null) { + if (spec.isIgnoreAdditionalSpecifications()) { + break; } + return null; + } + + boolean implicit = typeIndex < spec.getImplicitRequiredTypes().size(); + int typeVarArgsIndex = typeVarArgs ? typeIndex - types.size() + 1 : -1; + int specVarArgsIndex = specVarArgs ? specificationIndex - specifications.size() + 1 : -1; + + if (typeVarArgsIndex >= 0 && specVarArgsIndex >= 0) { + // both specifications and types have a variable number of arguments + // we would get into an endless loop if we would continue break; } - TypeMirror actualType = types.get(); - if (varArgs && types.isLast()) { - if (actualType.getKind() == TypeKind.ARRAY) { - actualType = ((ArrayType) actualType).getComponentType(); - } - varArgsParameterIndex++; + + ActualParameter resolvedParameter = matchParameter(specification, actualType, template, specVarArgsIndex, typeVarArgsIndex, implicit); + if (resolvedParameter == null) { + return null; } - boolean implicit = types.getIndex() < spec.getImplicitRequiredTypes().size(); - ActualParameter resolvedParameter = matchParameter(required.get(), actualType, template, specificationParameterIndex, varArgsParameterIndex, implicit); - if (resolvedParameter == null) { - if (required.get().getCardinality() == Cardinality.MANY) { - required.consume(); - continue; - } - // direct mismatch but required -> error - return null; + parsedParams.add(resolvedParameter); + typeIndex++; + specificationIndex++; + } + + if (typeIndex < types.size()) { + // additional types available + if (spec.isIgnoreAdditionalParameters()) { + return parsedParams; } else { - parsedParams.add(resolvedParameter); - - if (varArgs && types.isLast()) { - /* Both varargs spec and varargs definition. Need to consume to terminate. */ - if (required.get().getCardinality() == Cardinality.MANY) { - types.consume(); - } - } else { - types.consume(); - } - - if (required.get().getCardinality() == Cardinality.ONE) { - required.consume(); - specificationParameterIndex = 0; - } else if (required.get().getCardinality() == Cardinality.MANY) { - specificationParameterIndex++; - } + return null; } } - if (!types.toList().isEmpty() && !(varArgs && types.isLast())) { - // additional types -> error - return null; - } - - if (!required.toList().isEmpty() && !spec.isVariableRequiredArguments()) { - // additional specifications -> error - return null; - } return parsedParams; } - private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int specificationIndex, int varArgsIndex, boolean implicit) { + private static ParameterSpec nextSpecification(List specifications, int specIndex, boolean varArgs) { + if (varArgs && specIndex >= specifications.size() - 1 && !specifications.isEmpty()) { + return specifications.get(specifications.size() - 1); + } else if (specIndex < specifications.size()) { + return specifications.get(specIndex); + } else { + return null; + } + } + + private static TypeMirror nextActualType(List types, int typeIndex, boolean varArgs) { + if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) { + // unpack varargs array argument + TypeMirror actualType = types.get(types.size() - 1); + if (actualType.getKind() == TypeKind.ARRAY) { + actualType = ((ArrayType) actualType).getComponentType(); + } + return actualType; + } else if (typeIndex < types.size()) { + return types.get(typeIndex); + } else { + return null; + } + } + + protected final ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int specificationIndex, int varArgsIndex, boolean implicit) { TypeMirror resolvedType = mirror; if (hasError(resolvedType)) { resolvedType = context.resolveNotYetCompiledType(mirror, originalTemplate); @@ -355,57 +355,7 @@ } } - /* Helper class for parsing. */ - private static class ConsumableListIterator implements Iterable { - - private final List data; - private int index; - - public ConsumableListIterator(List data) { - this.data = data; - } - - public E get() { - if (index >= data.size()) { - return null; - } - return data.get(index); - } - - public boolean isLast() { - return index == data.size() - 1; - } - - public E consume() { - return consume(1); - } - - public E consume(int count) { - if (index + count <= data.size()) { - index += count; - return get(); - } else { - throw new ArrayIndexOutOfBoundsException(count + 1); - } - } - - public int getIndex() { - return index; - } - - @Override - public Iterator iterator() { - return toList().iterator(); - } - - public List toList() { - if (index < data.size()) { - return data.subList(index, data.size()); - } else { - return Collections. emptyList(); - } - } - + public final E create(String id, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List parameterTypes) { + return parseImpl(createSpecification(methodMetadata, mirror), id, methodMetadata, mirror, returnType, parameterTypes); } - } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateParser.java Tue Jan 07 14:41:52 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * 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.dsl.processor.template; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.dsl.processor.*; - -public abstract class TemplateParser extends AbstractParser { - - public TemplateParser(ProcessorContext c) { - super(c); - } - - protected void verifyExclusiveMethodAnnotation(Template template, Class... annotationTypes) { - List methods = ElementFilter.methodsIn(template.getTemplateType().getEnclosedElements()); - for (ExecutableElement method : methods) { - List foundAnnotations = new ArrayList<>(); - for (int i = 0; i < annotationTypes.length; i++) { - Class annotationType = annotationTypes[i]; - AnnotationMirror mirror = Utils.findAnnotationMirror(context.getEnvironment(), method, annotationType); - if (mirror != null) { - foundAnnotations.add(mirror); - } - } - if (foundAnnotations.size() > 1) { - List annotationNames = new ArrayList<>(); - for (AnnotationMirror mirror : foundAnnotations) { - annotationNames.add("@" + Utils.getSimpleName(mirror.getAnnotationType())); - } - - template.addError("Non exclusive usage of annotations %s.", annotationNames); - } - } - } - -} diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java Tue Jan 07 18:53:04 2014 +0100 @@ -23,10 +23,8 @@ package com.oracle.truffle.dsl.processor.typesystem; import java.lang.annotation.*; -import java.util.*; import javax.lang.model.element.*; -import javax.lang.model.type.*; import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.node.*; @@ -53,16 +51,18 @@ } @Override + protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) { + return super.createValueParameterSpec(execution); + } + + @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null); - spec.setVariableRequiredArguments(true); + spec.setIgnoreAdditionalSpecifications(true); spec.getRequired().clear(); for (ActualParameter parameter : specialization.getRequiredParameters()) { - List assignableTypes = Utils.getAssignableTypes(getContext(), parameter.getType()); - ParameterSpec paramSpec = new ParameterSpec(parameter.getLocalName(), assignableTypes); - paramSpec.setSignature(true); - spec.addRequired(paramSpec); + spec.addRequired(new ParameterSpec(parameter.getSpecification(), Utils.getAssignableTypes(getContext(), parameter.getType()))); } return spec; @@ -80,31 +80,7 @@ @Override public GuardData create(TemplateMethod method, boolean invalid) { - GuardData guard = new GuardData(method, specialization, negated); - /* - * Update parameters in way that parameter specifications match again the node field names - * etc. - */ - List newParameters = new ArrayList<>(); - for (ActualParameter parameter : guard.getParameters()) { - ActualParameter specializationParameter = specialization.findParameter(parameter.getSpecification().getName()); - if (specializationParameter == null) { - newParameters.add(parameter); - } else { - ActualParameter p; - if (parameter.getTypeSystemType() != null) { - p = new ActualParameter(specializationParameter.getSpecification(), parameter.getTypeSystemType(), specializationParameter.getSpecificationIndex(), - specializationParameter.getVarArgsIndex(), parameter.isImplicit()); - } else { - p = new ActualParameter(specializationParameter.getSpecification(), parameter.getType(), specializationParameter.getSpecificationIndex(), - specializationParameter.getVarArgsIndex(), parameter.isImplicit()); - } - newParameters.add(p); - } - } - guard.setParameters(newParameters); - - return guard; + return new GuardData(method, specialization, negated); } @Override diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java Tue Jan 07 18:53:04 2014 +0100 @@ -50,7 +50,7 @@ types.add(typeData.getPrimitiveType()); } MethodSpec spec = new MethodSpec(new ParameterSpec("target", types)); - spec.addRequired(new ParameterSpec("source", types)).setSignature(true); + spec.addRequired(new ParameterSpec("source", types)); return spec; } diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java Tue Jan 07 18:53:04 2014 +0100 @@ -35,7 +35,7 @@ import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.template.*; -public class TypeSystemParser extends TemplateParser { +public class TypeSystemParser extends AbstractParser { public static final List> ANNOTATIONS = Arrays.asList(TypeSystem.class, ExpectError.class); @@ -115,6 +115,28 @@ return typeSystem; } + protected void verifyExclusiveMethodAnnotation(Template template, Class... annotationTypes) { + List methods = ElementFilter.methodsIn(template.getTemplateType().getEnclosedElements()); + for (ExecutableElement method : methods) { + List foundAnnotations = new ArrayList<>(); + for (int i = 0; i < annotationTypes.length; i++) { + Class annotationType = annotationTypes[i]; + AnnotationMirror mirror = Utils.findAnnotationMirror(context.getEnvironment(), method, annotationType); + if (mirror != null) { + foundAnnotations.add(mirror); + } + } + if (foundAnnotations.size() > 1) { + List annotationNames = new ArrayList<>(); + for (AnnotationMirror mirror : foundAnnotations) { + annotationNames.add("@" + Utils.getSimpleName(mirror.getAnnotationType())); + } + + template.addError("Non exclusive usage of annotations %s.", annotationNames); + } + } + } + private static void verifyGenericTypeChecksAndCasts(TypeSystemData typeSystem) { for (TypeData type : typeSystem.getTypes()) { if (!type.getTypeChecks().isEmpty()) { diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Filterator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Filterator.java Tue Jan 07 18:53:04 2014 +0100 @@ -0,0 +1,85 @@ +/* + * 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.dsl.processor.util; + +import java.util.*; + +public class Filterator implements Iterator { + + private final Predicate includePredicate; + private final Iterator elements; + + private boolean hasCached; + private T cached; + + public Filterator(Iterator elements, Predicate includePredicate) { + this.elements = elements; + this.includePredicate = includePredicate; + } + + public boolean hasNext() { + if (hasCached) { + return true; + } + nextValue(); + return hasCached; + } + + private void nextValue() { + while (!hasCached && elements.hasNext()) { + T element = elements.next(); + if (includePredicate.evaluate(element)) { + cached = element; + hasCached = true; + } + } + } + + public T next() { + T foundCached = getCached(); + if (foundCached != null) { + return foundCached; + } else { + nextValue(); + if (!hasCached) { + throw new NoSuchElementException(); + } + return getCached(); + } + } + + private T getCached() { + if (hasCached) { + hasCached = false; + T value = cached; + cached = null; + return value; + } + return null; + } + + public void remove() { + elements.remove(); + } + +} diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/FilteredIterable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/FilteredIterable.java Tue Jan 07 18:53:04 2014 +0100 @@ -0,0 +1,41 @@ +/* + * 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.dsl.processor.util; + +import java.util.*; + +public class FilteredIterable implements Iterable { + + private final Iterable delegate; + private final Predicate containedPredicate; + + public FilteredIterable(Iterable delegate, Predicate containedPredicate) { + this.delegate = delegate; + this.containedPredicate = containedPredicate; + } + + public Iterator iterator() { + return new Filterator<>(delegate.iterator(), containedPredicate); + } + +} diff -r 56452e07874f -r 856c2c294f84 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Predicate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Predicate.java Tue Jan 07 18:53:04 2014 +0100 @@ -0,0 +1,29 @@ +/* + * 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.dsl.processor.util; + +public interface Predicate { + + boolean evaluate(T value); + +} diff -r 56452e07874f -r 856c2c294f84 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 Tue Jan 07 14:41:52 2014 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java Tue Jan 07 18:53:04 2014 +0100 @@ -16,7 +16,7 @@ * 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 + * 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. */