# HG changeset patch # User Christian Humer # Date 1372705112 -7200 # Node ID 79041ab4366075505b88d958426b1f304b69a33b # Parent f43eb2f1bbbc132cbeea1a2844e0e757ba8a8452 Truffle-DSL: API-change: Renamed truffle.api.codegen to truffle.api.dsl for all projects and packages. diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/AssumptionsTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/AssumptionsTest.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +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.codegen.test; - -import org.junit.*; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.api.codegen.test.AssumptionsTestFactory.DerivedAssumptionNodeFactory; -import com.oracle.truffle.api.codegen.test.AssumptionsTestFactory.DerivedAssumptionRedeclaredNodeFactory; -import com.oracle.truffle.api.codegen.test.AssumptionsTestFactory.MultipleAssumptionsNodeFactory; -import com.oracle.truffle.api.codegen.test.AssumptionsTestFactory.SingleAssumptionNodeFactory; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode; - -public class AssumptionsTest { - - @Test - public void testSingleAssumption() { - Assumption assumption = Truffle.getRuntime().createAssumption(); - TestRootNode root = TestHelper.createRoot(SingleAssumptionNodeFactory.getInstance(), assumption); - - Assert.assertEquals(42, TestHelper.executeWith(root)); - assumption.invalidate(); - Assert.assertEquals("42", TestHelper.executeWith(root)); - } - - @NodeAssumptions("assumption") - abstract static class SingleAssumptionNode extends ValueNode { - - @Specialization(order = 0, assumptions = "assumption") - int doInt() { - return 42; - } - - @Specialization - Object doObject() { - return "42"; - } - } - - @Test - public void testMultipleAssumption() { - Assumption assumption1 = Truffle.getRuntime().createAssumption(); - Assumption assumption2 = Truffle.getRuntime().createAssumption(); - TestRootNode root = TestHelper.createRoot(MultipleAssumptionsNodeFactory.getInstance(), assumption1, assumption2); - - Assert.assertEquals(42, TestHelper.executeWith(root)); - assumption2.invalidate(); - Assert.assertEquals("42", TestHelper.executeWith(root)); - assumption1.invalidate(); - Assert.assertEquals("43", TestHelper.executeWith(root)); - } - - @NodeAssumptions({"assumption1", "assumption2"}) - abstract static class MultipleAssumptionsNode extends ValueNode { - - @Specialization(assumptions = {"assumption1", "assumption2"}) - int doInt() { - return 42; - } - - @Specialization(assumptions = "assumption1") - Object doObject() { - return "42"; - } - - @Generic - Object doGeneric() { - return "43"; - } - } - - @Test - public void testDerivedAssumption() { - Assumption additionalAssumption = Truffle.getRuntime().createAssumption(); - Assumption assumption = Truffle.getRuntime().createAssumption(); - TestRootNode root = TestHelper.createRoot(DerivedAssumptionNodeFactory.getInstance(), assumption, additionalAssumption); - - Assert.assertEquals(42, TestHelper.executeWith(root)); - assumption.invalidate(); - Assert.assertEquals(43, TestHelper.executeWith(root)); - additionalAssumption.invalidate(); - Assert.assertEquals("42", TestHelper.executeWith(root)); - } - - @NodeAssumptions({"additionalAssumption"}) - abstract static class DerivedAssumptionNode extends SingleAssumptionNode { - - @Specialization(order = 1, assumptions = "additionalAssumption") - int doIntDerived() { - return 43; - } - } - - @Test - public void testDerivedAssumptionRedeclared() { - Assumption additionalAssumption = Truffle.getRuntime().createAssumption(); - Assumption assumption = Truffle.getRuntime().createAssumption(); - TestRootNode root = TestHelper.createRoot(DerivedAssumptionRedeclaredNodeFactory.getInstance(), additionalAssumption, assumption); - - Assert.assertEquals(42, TestHelper.executeWith(root)); - assumption.invalidate(); - Assert.assertEquals(43, TestHelper.executeWith(root)); - additionalAssumption.invalidate(); - Assert.assertEquals("42", TestHelper.executeWith(root)); - } - - @NodeAssumptions({"additionalAssumption", "assumption"}) - abstract static class DerivedAssumptionRedeclaredNode extends SingleAssumptionNode { - - @Specialization(order = 1, assumptions = "additionalAssumption") - int doIntDerived() { - return 43; - } - - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryNodeTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryNodeTest.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +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.codegen.test; - -import static com.oracle.truffle.api.codegen.test.TestHelper.*; -import static org.junit.Assert.*; - -import org.junit.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.api.codegen.test.BinaryNodeTestFactory.AddNodeFactory; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode; - -public class BinaryNodeTest { - - @Test - public void testAdd() { - TestRootNode node = createRoot(AddNodeFactory.getInstance()); - assertEquals(42, executeWith(node, 19, 23)); - assertEquals(42d, executeWith(node, 19d, 23d)); - assertEquals(42d, executeWith(node, "19", "23")); - assertEquals(42, executeWith(node, 19, 23)); - } - - @Test(expected = RuntimeException.class) - public void testAddUnsupported() { - TestRootNode node = createRoot(AddNodeFactory.getInstance()); - executeWith(node, new Object(), new Object()); - } - - @NodeChildren({@NodeChild("left"), @NodeChild("right")}) - abstract static class BinaryNode extends ValueNode { - } - - abstract static class AddNode extends BinaryNode { - - @Specialization - int add(int left, int right) { - return left + right; - } - - @Generic - Object add(Object left, Object right) { - return convertDouble(left) + convertDouble(right); - } - - static double convertDouble(Object value) { - if (value instanceof Number) { - return ((Number) value).doubleValue(); - } else if (value instanceof String) { - return Double.parseDouble((String) value); - } - throw new RuntimeException("Invalid datatype"); - } - - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/ExecuteEvaluatedTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/ExecuteEvaluatedTest.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +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.codegen.test; - -import org.junit.*; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.api.codegen.test.ExecuteEvaluatedTestFactory.DoubleEvaluatedNodeFactory; -import com.oracle.truffle.api.codegen.test.ExecuteEvaluatedTestFactory.EvaluatedNodeFactory; -import com.oracle.truffle.api.codegen.test.ExecuteEvaluatedTestFactory.UseDoubleEvaluatedNodeFactory; -import com.oracle.truffle.api.codegen.test.ExecuteEvaluatedTestFactory.UseEvaluatedNodeFactory; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.ArgumentNode; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestArguments; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; - -public class ExecuteEvaluatedTest { - - @Test - public void testSingleEvaluated() { - ArgumentNode arg0 = new ArgumentNode(0); - CallTarget callTarget = TestHelper.createCallTarget(UseEvaluatedNodeFactory.create(arg0, EvaluatedNodeFactory.create(null))); - - Assert.assertEquals(43, callTarget.call(new TestArguments(42))); - Assert.assertEquals(1, arg0.getInvocationCount()); - } - - @NodeChild("exp") - abstract static class EvaluatedNode extends ValueNode { - - @Specialization - int doExecuteWith(int exp) { - return exp + 1; - } - - public abstract Object executeEvaluated(VirtualFrame frame, Object targetValue); - - public abstract int executeIntEvaluated(VirtualFrame frame, Object targetValue) throws UnexpectedResultException; - } - - @NodeChildren({@NodeChild("exp0"), @NodeChild(value = "exp1", type = EvaluatedNode.class, executeWith = "exp0")}) - abstract static class UseEvaluatedNode extends ValueNode { - - @Specialization - int call(int exp0, int exp1) { - Assert.assertEquals(exp0 + 1, exp1); - return exp1; - } - } - - @Test - public void testDoubleEvaluated() { - ArgumentNode arg0 = new ArgumentNode(0); - ArgumentNode arg1 = new ArgumentNode(1); - CallTarget callTarget = TestHelper.createCallTarget(UseDoubleEvaluatedNodeFactory.create(arg0, arg1, DoubleEvaluatedNodeFactory.create(null, null))); - - Assert.assertEquals(85, callTarget.call(new TestArguments(42, 43))); - Assert.assertEquals(1, arg0.getInvocationCount()); - Assert.assertEquals(1, arg1.getInvocationCount()); - } - - @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1")}) - abstract static class DoubleEvaluatedNode extends ValueNode { - - @Specialization - int doExecuteWith(int exp0, int exp1) { - return exp0 + exp1; - } - - public abstract Object executeEvaluated(VirtualFrame frame, Object exp0, Object exp1); - - public abstract int executeIntEvaluated(VirtualFrame frame, Object exp0, Object exp1) throws UnexpectedResultException; - } - - @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1"), @NodeChild(value = "exp2", type = DoubleEvaluatedNode.class, executeWith = {"exp0", "exp1"})}) - abstract static class UseDoubleEvaluatedNode extends ValueNode { - - @Specialization - int call(int exp0, int exp1, int exp2) { - Assert.assertEquals(exp0 + exp1, exp2); - return exp2; - } - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/GuardsTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/GuardsTest.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +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.codegen.test; - -import static com.oracle.truffle.api.codegen.test.TestHelper.*; - -import org.junit.*; -import static org.junit.Assert.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.api.codegen.test.GuardsTestFactory.GlobalFlagGuardFactory; -import com.oracle.truffle.api.codegen.test.GuardsTestFactory.InvocationGuardFactory; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode; - -@SuppressWarnings("unused") -public class GuardsTest { - - private static final Object NULL = new Object(); - - @Test - public void testGuardInvocations() { - TestRootNode root = createRoot(InvocationGuardFactory.getInstance()); - - assertEquals(Integer.MAX_VALUE, executeWith(root, Integer.MAX_VALUE - 1, 1)); - assertEquals(1, InvocationGuard.specializedInvocations); - assertEquals(0, InvocationGuard.genericInvocations); - - assertEquals(42, executeWith(root, Integer.MAX_VALUE, 1)); - assertEquals(1, InvocationGuard.specializedInvocations); - assertEquals(1, InvocationGuard.genericInvocations); - } - - @NodeChildren({@NodeChild("value0"), @NodeChild("value1")}) - public abstract static class InvocationGuard extends ValueNode { - - static int specializedInvocations = 0; - static int genericInvocations = 0; - - boolean guard(int value0, int value1) { - return value0 != Integer.MAX_VALUE; - } - - @Specialization(guards = "guard") - int doSpecialized(int value0, int value1) { - specializedInvocations++; - return value0 + value1; - } - - @Generic - int doGeneric(Object value0, Object value1) { - genericInvocations++; - return 42; // the generic answer to all questions - } - } - - @Test - public void testGuardGlobal() { - TestRootNode root = createRoot(GlobalFlagGuardFactory.getInstance()); - - assertEquals(42, executeWith(root, NULL)); - - GlobalFlagGuard.globalFlag = true; - assertEquals(41, executeWith(root, NULL)); - - GlobalFlagGuard.globalFlag = false; - assertEquals(42, executeWith(root, NULL)); - } - - @NodeChild("expression") - public abstract static class GlobalFlagGuard extends ValueNode { - - static boolean globalFlag = false; - - static boolean globalFlagGuard() { - return globalFlag; - } - - @Specialization(guards = "globalFlagGuard") - int doSpecialized(Object value0) { - return 41; - } - - @Generic - int doGeneric(Object value0) { - return 42; // the generic answer to all questions - } - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/NodeContainerTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/NodeContainerTest.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,186 +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.codegen.test; - -import static com.oracle.truffle.api.codegen.test.TestHelper.*; -import static org.junit.Assert.*; - -import org.junit.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.api.codegen.test.NodeContainerTestFactory.StrFactory.StrAccessContextFactory; -import com.oracle.truffle.api.codegen.test.NodeContainerTestFactory.StrFactory.StrConcatFactory; -import com.oracle.truffle.api.codegen.test.NodeContainerTestFactory.StrFactory.StrLengthFactory; -import com.oracle.truffle.api.codegen.test.NodeContainerTestFactory.StrFactory.StrSubstrFactory; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode; -import com.oracle.truffle.api.codegen.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)); - } - - @NodeContainer(BuiltinNode.class) - static class Str { - - 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) - abstract static class BuiltinNode extends ValueNode { - - protected final Context context; - - public BuiltinNode(BuiltinNode node) { - this(node.context); - } - - public BuiltinNode(Context context) { - this.context = context; - } - - public Context getContext() { - return context; - } - } - - static class Context { - - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/PolymorphicTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/PolymorphicTest.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +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.codegen.test; - -import static com.oracle.truffle.api.codegen.test.TestHelper.*; -import static org.junit.Assert.*; - -import org.junit.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.api.codegen.test.BinaryNodeTest.BinaryNode; -import com.oracle.truffle.api.codegen.test.PolymorphicTestFactory.Node1Factory; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.NodeInfo.Kind; - -public class PolymorphicTest { - - @Test - public void testJustSpecialize() { - TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); - assertEquals("(int,int)", executeWith(node, 42, 42)); - assertEquals("(boolean,boolean)", executeWith(node, false, false)); - assertEquals("(int,boolean)", executeWith(node, 42, false)); - assertEquals("(boolean,int)", executeWith(node, false, 42)); - assertEquals(Kind.SPECIALIZED, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); - } - - @Test - public void testPolymorphic2() { - TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); - assertEquals("(int,boolean)", executeWith(node, 42, false)); - assertEquals("(int,int)", executeWith(node, 42, 42)); - assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); - } - - @Test - public void testPolymorphic3() { - TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); - assertEquals("(int,boolean)", executeWith(node, 42, false)); - assertEquals("(boolean,boolean)", executeWith(node, true, false)); - assertEquals("(int,int)", executeWith(node, 42, 42)); - assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); - } - - @Test - public void testGenericLimitReached() { - TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); - assertEquals("(boolean,int)", executeWith(node, false, 42)); - assertEquals("(int,boolean)", executeWith(node, 42, false)); - assertEquals("(boolean,boolean)", executeWith(node, true, false)); - assertEquals("(int,int)", executeWith(node, 42, 42)); - assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); - } - - @Test - public void testGenericInitial() { - TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); - assertEquals("(generic,generic)", executeWith(node, "", "")); - assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); - } - - @Test - public void testGenericPolymorphic() { - TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); - assertEquals("(boolean,int)", executeWith(node, false, 42)); - assertEquals("(int,boolean)", executeWith(node, 42, false)); - assertEquals("(generic,generic)", executeWith(node, "", "")); - assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); - } - - @SuppressWarnings("unused") - @PolymorphicLimit(3) - abstract static class Node1 extends BinaryNode { - - @Specialization(order = 1) - String add(int left, int right) { - return "(int,int)"; - } - - @Specialization(order = 2) - String add(boolean left, boolean right) { - return "(boolean,boolean)"; - } - - @Specialization(order = 3) - String add(int left, boolean right) { - return "(int,boolean)"; - } - - @Specialization(order = 4) - String add(boolean left, int right) { - return "(boolean,int)"; - } - - @Generic - String add(Object left, Object right) { - return "(generic,generic)"; - } - - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.codegen.test; - -import java.util.*; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.api.codegen.test.NodeContainerTest.*; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.*; - -/** - * Utility class to provide some test helper functions. - */ -class TestHelper { - - private static ArgumentNode[] arguments(int count) { - ArgumentNode[] nodes = new ArgumentNode[count]; - for (int i = 0; i < nodes.length; i++) { - nodes[i] = new ArgumentNode(i); - } - return nodes; - } - - static E createNode(NodeFactory factory, Object... constants) { - ArgumentNode[] argumentNodes = arguments(factory.getExecutionSignature().size()); - - List argumentList = new ArrayList<>(); - argumentList.addAll(Arrays.asList(constants)); - if (ChildrenNode.class.isAssignableFrom(factory.getNodeClass()) || BuiltinNode.class.isAssignableFrom(factory.getNodeClass())) { - argumentList.add(argumentNodes); - } else { - argumentList.addAll(Arrays.asList(argumentNodes)); - } - return factory.createNode(argumentList.toArray(new Object[argumentList.size()])); - } - - static TestRootNode createRoot(NodeFactory factory, Object... constants) { - return new TestRootNode<>(createNode(factory, constants)); - } - - static CallTarget createCallTarget(ValueNode node) { - return createCallTarget(new TestRootNode<>(node)); - } - - static CallTarget createCallTarget(TestRootNode node) { - return Truffle.getRuntime().createCallTarget(node); - } - - static Object executeWith(TestRootNode node, Object... values) { - return createCallTarget(node).call(new TestArguments(values)); - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.codegen.test; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.api.codegen.test.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, Object[].class}) - static class SimpleTypes { - } - - @TypeSystemReference(SimpleTypes.class) - public abstract static class ValueNode extends Node { - - public int executeInt(VirtualFrame frame) throws UnexpectedResultException { - 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)); - } - - public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException { - return SimpleTypesGen.SIMPLETYPES.expectBoolean(execute(frame)); - } - - public Object[] executeIntArray(VirtualFrame frame) throws UnexpectedResultException { - return SimpleTypesGen.SIMPLETYPES.expectObjectArray(execute(frame)); - } - - public abstract Object execute(VirtualFrame frame); - - @Override - public ValueNode copy() { - return (ValueNode) super.copy(); - } - } - - @NodeChild(value = "children", type = ValueNode[].class) - public abstract static class ChildrenNode extends ValueNode { - - } - - @TypeSystemReference(SimpleTypes.class) - public static class TestRootNode extends RootNode { - - @Child private E node; - - public TestRootNode(E node) { - this.node = adoptChild(node); - } - - @Override - public Object execute(VirtualFrame frame) { - return node.execute(frame); - } - - public E getNode() { - return node; - } - } - - public static class TestArguments extends Arguments { - - private final Object[] values; - - public TestArguments(Object... values) { - this.values = values; - } - - public Object[] getValues() { - return values; - } - - public Object get(int index) { - return values[index]; - } - - } - - public static class ArgumentNode extends ValueNode { - - private int invocationCount; - final int index; - - public ArgumentNode(int index) { - this.index = index; - } - - public int getInvocationCount() { - return invocationCount; - } - - @Override - public Object execute(VirtualFrame frame) { - invocationCount++; - return frame.getArguments(TestArguments.class).get(index); - } - - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/package-info.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/package-info.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +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. - */ -/** - *

This package contains basic tests of the Truffle-Source-Code-Generation (short Codegen) API and serves at the same - * time as an introduction to the Codegen API for language implementors. Every test gives an example on how to use the construct explained in the class description.

- * - *

- * This API relies heavily on the concepts described in com.oracle.truffle.api.test. We assume that the - * reader is already familiarized with those concepts. - *

- * - *

- * TODO general description - *

- * - *

- * This introduction to Codegen contains items in the following recommended order: - * - * Prerequisites: - * - * - *

    - *
  • What do I need to get started? {@link com.oracle.truffle.api.codegen.test.TypeSystemTest}
  • - *
  • How would you generate function nodes for runtime objects? {@link com.oracle.truffle.api.codegen.test.NodeContainerTest}
  • - *
- *

- * - */ -package com.oracle.truffle.api.codegen.test; - diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/CreateCast.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/CreateCast.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +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.codegen; - -import java.lang.annotation.*; - -import com.oracle.truffle.api.nodes.*; - -/** - * Specifies a factory method that creates a {@link Node} which is used to cast this child. - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD}) -public @interface CreateCast { - - String[] value(); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GeneratedBy.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GeneratedBy.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +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.codegen; - -import java.lang.annotation.*; - -/** - * Marks a type to be generated by another class or a method. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface GeneratedBy { - - Class value(); - - String methodName() default ""; - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Generic.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Generic.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +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.codegen; - -import java.lang.annotation.*; - -/** - * - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD}) -public @interface Generic { - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeAssumptions.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeAssumptions.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +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.codegen; - -import java.lang.annotation.*; - -/** - * Declares one or multiple assumptions for use inside a source code generation enabled node. - * Declared assumptions must be passed to the {@link NodeFactory#createNode(Object...)} method as - * parameters. - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.TYPE}) -public @interface NodeAssumptions { - - String[] value(); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +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.codegen; - -import java.lang.annotation.*; - -import com.oracle.truffle.api.nodes.*; - -/** - * A {@link NodeChild} element defines an executable child for the enclosing {@link Node}. A - * {@link Node} contains multiple {@link NodeChildren} specified in linear execution order. - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.TYPE}) -public @interface NodeChild { - - String value() default ""; - - Class type() default Node.class; - - /** - * The {@link #executeWith()} property allows a node to pass the result of one child's - * executable as an input to another child's executable. These referenced children must be - * defined before the current node in the execution order. The current node {@link #type()} - * attribute must be set to a {@link Node} which supports the evaluated execution with the - * number of {@link #executeWith()} arguments that are defined. For example if this child is - * executed with one argument, the {@link #type()} attribute must define a node which publicly - * declares a method with the signature Object execute*(VirtualFrame, Object). - */ - String[] executeWith() default {}; -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChildren.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChildren.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +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.codegen; - -import java.lang.annotation.*; - -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.TYPE}) -public @interface NodeChildren { - - NodeChild[] value() default {}; - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeContainer.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeContainer.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +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.codegen; - -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 f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeFactory.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeFactory.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +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.codegen; - -import java.util.*; - -import com.oracle.truffle.api.nodes.*; - -/** - * Enables the dynamic creation of generated nodes. It provides an convenient way to instantiate - * generated node classes without using reflection. - */ -public interface NodeFactory { - - /** - * Instantiates the node using the arguments array. The arguments length and types must suffice - * one of the returned signatures in {@link #getNodeSignatures()}. If the arguments array does - * not suffice one of the node signatures an {@link IllegalArgumentException} is thrown. - * - * @param arguments the argument values - * @return the instantiated node - * @throws IllegalArgumentException - */ - T createNode(Object... arguments); - - /** - * Instantiates a new generic variant of the node. This is an optional method and throws an - * {@link UnsupportedOperationException} if not supported. - * - * @param thisNode the current node - * @return the specialized node - */ - T createNodeGeneric(T thisNode); - - /** - * Returns the node class that will get created by {@link #createNode(Object...)}. The node - * class does not match exactly to the instantiated object but they are guaranteed to be - * assignable. - */ - Class getNodeClass(); - - /** - * Returns a list of signatures that can be used to invoke {@link #createNode(Object...)}. - */ - List>> getNodeSignatures(); - - /** - * Returns a list of children that will be executed by the created node. This is useful for base - * nodes that can execute a variable amount of nodes. - */ - List> getExecutionSignature(); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeId.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeId.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +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.codegen; - -import java.lang.annotation.*; - -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD, ElementType.TYPE}) -public @interface NodeId { - - String value(); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/PolymorphicLimit.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/PolymorphicLimit.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +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.codegen; - -import java.lang.annotation.*; - -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.TYPE}) -public @interface PolymorphicLimit { - - /** Specifies the maximum polymorphic cache depth until it falls back to the generic case. */ - int value(); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ShortCircuit.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ShortCircuit.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +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.codegen; - -import java.lang.annotation.*; - -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD}) -public @interface ShortCircuit { - - String value(); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Specialization.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Specialization.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +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.codegen; - -import java.lang.annotation.*; - -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD}) -public @interface Specialization { - - int DEFAULT_ORDER = -1; - - int order() default DEFAULT_ORDER; - - Class[] rewriteOn() default {}; - - String[] guards() default {}; - - /** - * Defines the assumptions to check for this specialization. When the specialization method is - * invoked it is guaranteed that the assigned assumptions still hold. To declare assumptions use - * the {@link NodeAssumptions} annotation at class level. - */ - String[] assumptions() default {}; - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationListener.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationListener.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +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.codegen; - -import java.lang.annotation.*; - -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD}) -public @interface SpecializationListener { -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCast.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCast.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +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.codegen; - -import java.lang.annotation.*; - -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD}) -public @interface TypeCast { - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCheck.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCheck.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +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.codegen; - -import java.lang.annotation.*; - -/** - *

- * Provides a way to define a custom type check for a defined type. The name of the annotated method - * must fit to the pattern is${typeName} (eg. isInteger), where ${typeName} must be a valid type - * defined in the parent {@link TypeSystem}. The annotated method must have exactly one argument - * where the type of the argument is the generic type {@link Object} or a more specific one from the - * {@link TypeSystem}. You can define multiple overloaded {@link TypeCheck} methods for the same - * type. This can be used to reduce the boxing overhead in type conversions. - *

- * - *

- * By default the system generates type checks for all types in the parent {@link TypeSystem} which - * look like the follows: - * - *

- * {@literal @}TypeCheck
- * boolean is${typeName}(Object value) {
- *         return value instanceof ${typeName};
- * }
- * 
- * - *

- * - * Example: - *

- * A type check for BigInteger with one overloaded optimized variant to reduce boxing. - *

- * - *
- * 
- * 
- * {@literal @}TypeSystem(types = {int.class, BigInteger.class, String.class}, nodeBaseClass = TypedNode.class)
- * public abstract class Types {
- * 
- *     {@literal @}TypeCheck
- *     public boolean isBigInteger(Object value) {
- *         return value instanceof Integer || value instanceof BigInteger;
- *     }
- * 
- *     {@literal @}TypeCheck
- *     public boolean isBigInteger(int value) {
- *         return true;
- *     }
- * 
- * }
- * 
- * - * - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD}) -public @interface TypeCheck { - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +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.codegen; - -import java.lang.annotation.*; - -import com.oracle.truffle.api.nodes.*; - -/** - *

- * Each {@link Node} has one {@link TypeSystem} at its root to define the types that can be used - * throughout the system. Multiple {@link TypeSystem}s are allowed, but they cannot be mixed inside - * a single {@link Node} hierarchy. A {@link TypeSystem} defines a list of types as its child - * elements, in which every type precedes its super types.The latter condition ensures that the most - * concrete type is found first when searching the list sequentially for the type of a given generic - * value. - *

- * - *

- * Each {@link #value()} is represented as a java type. A type can specify two annotations: - * {@link TypeCheck} and {@link TypeCast}. The {@link TypeCheck} checks whether a given generic - * value matches to the current type. The {@link TypeCast} casts a generic type value to the current - * type. If the {@link TypeCheck} and {@link TypeCast} annotations are not declared in the - * {@link TypeSystem} the a default implementation is provided. The default implementation of - * {@link TypeCheck} returns true only on an exact type match and {@link TypeCast} is - * only a cast to this type. Specified methods with {@link TypeCheck} and {@link TypeCast} may be - * used to extend the definition of a type in the language. In our example, the - * isInteger and asInteger methods are defined in a way so that they - * accept also {@link Integer} values, implicitly converting them to {@link Double} . This example - * points out how we express implicit type conversions. - *

- * - *

- * Example: The {@link TypeSystem} contains the types {@link Boolean}, {@link Integer}, and - * {@link Double}. The type {@link Object} is always used implicitly as the generic type represent - * all values. - * - *

- * 
- * {@literal @}TypeSystem(types = {boolean.class, int.class, double.class})
- * public abstract class ExampleTypeSystem {
- * 
- *     {@literal @}TypeCheck
- *     public boolean isInteger(Object value) {
- *         return value instanceof Integer || value instanceof Double;
- *     }
- * 
- *     {@literal @}TypeCast
- *     public double asInteger(Object value) {
- *         return ((Number)value).doubleValue();
- *     }
- * }
- * 
- * - *

- * - * @see TypeCast - * @see TypeCheck - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.TYPE}) -public @interface TypeSystem { - - /** - * The list of types as child elements of the {@link TypeSystem}. Each precedes its super type. - */ - Class[] value(); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystemReference.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystemReference.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +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.codegen; - -import java.lang.annotation.*; - -import com.oracle.truffle.api.nodes.*; - -/** - * References a {@link TypeSystem} on a node. Must be applied on a {@link Node} class. At least one - * {@link TypeSystem} must be referenced in a {@link Node}'s type hierarchy. - * - * @see TypeSystem - * @see Node - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.TYPE}) -public @interface TypeSystemReference { - - /** The {@link TypeSystem} java type. */ - Class value(); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.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/AssumptionsTest.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,139 @@ +/* + * 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 org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.DerivedAssumptionNodeFactory; +import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.DerivedAssumptionRedeclaredNodeFactory; +import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.MultipleAssumptionsNodeFactory; +import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.SingleAssumptionNodeFactory; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; + +public class AssumptionsTest { + + @Test + public void testSingleAssumption() { + Assumption assumption = Truffle.getRuntime().createAssumption(); + TestRootNode root = TestHelper.createRoot(SingleAssumptionNodeFactory.getInstance(), assumption); + + Assert.assertEquals(42, TestHelper.executeWith(root)); + assumption.invalidate(); + Assert.assertEquals("42", TestHelper.executeWith(root)); + } + + @NodeAssumptions("assumption") + abstract static class SingleAssumptionNode extends ValueNode { + + @Specialization(order = 0, assumptions = "assumption") + int doInt() { + return 42; + } + + @Specialization + Object doObject() { + return "42"; + } + } + + @Test + public void testMultipleAssumption() { + Assumption assumption1 = Truffle.getRuntime().createAssumption(); + Assumption assumption2 = Truffle.getRuntime().createAssumption(); + TestRootNode root = TestHelper.createRoot(MultipleAssumptionsNodeFactory.getInstance(), assumption1, assumption2); + + Assert.assertEquals(42, TestHelper.executeWith(root)); + assumption2.invalidate(); + Assert.assertEquals("42", TestHelper.executeWith(root)); + assumption1.invalidate(); + Assert.assertEquals("43", TestHelper.executeWith(root)); + } + + @NodeAssumptions({"assumption1", "assumption2"}) + abstract static class MultipleAssumptionsNode extends ValueNode { + + @Specialization(assumptions = {"assumption1", "assumption2"}) + int doInt() { + return 42; + } + + @Specialization(assumptions = "assumption1") + Object doObject() { + return "42"; + } + + @Generic + Object doGeneric() { + return "43"; + } + } + + @Test + public void testDerivedAssumption() { + Assumption additionalAssumption = Truffle.getRuntime().createAssumption(); + Assumption assumption = Truffle.getRuntime().createAssumption(); + TestRootNode root = TestHelper.createRoot(DerivedAssumptionNodeFactory.getInstance(), assumption, additionalAssumption); + + Assert.assertEquals(42, TestHelper.executeWith(root)); + assumption.invalidate(); + Assert.assertEquals(43, TestHelper.executeWith(root)); + additionalAssumption.invalidate(); + Assert.assertEquals("42", TestHelper.executeWith(root)); + } + + @NodeAssumptions({"additionalAssumption"}) + abstract static class DerivedAssumptionNode extends SingleAssumptionNode { + + @Specialization(order = 1, assumptions = "additionalAssumption") + int doIntDerived() { + return 43; + } + } + + @Test + public void testDerivedAssumptionRedeclared() { + Assumption additionalAssumption = Truffle.getRuntime().createAssumption(); + Assumption assumption = Truffle.getRuntime().createAssumption(); + TestRootNode root = TestHelper.createRoot(DerivedAssumptionRedeclaredNodeFactory.getInstance(), additionalAssumption, assumption); + + Assert.assertEquals(42, TestHelper.executeWith(root)); + assumption.invalidate(); + Assert.assertEquals(43, TestHelper.executeWith(root)); + additionalAssumption.invalidate(); + Assert.assertEquals("42", TestHelper.executeWith(root)); + } + + @NodeAssumptions({"additionalAssumption", "assumption"}) + abstract static class DerivedAssumptionRedeclaredNode extends SingleAssumptionNode { + + @Specialization(order = 1, assumptions = "additionalAssumption") + int doIntDerived() { + return 43; + } + + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BinaryNodeTest.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/BinaryNodeTest.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,79 @@ +/* + * 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.BinaryNodeTestFactory.AddNodeFactory; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; + +public class BinaryNodeTest { + + @Test + public void testAdd() { + TestRootNode node = createRoot(AddNodeFactory.getInstance()); + assertEquals(42, executeWith(node, 19, 23)); + assertEquals(42d, executeWith(node, 19d, 23d)); + assertEquals(42d, executeWith(node, "19", "23")); + assertEquals(42, executeWith(node, 19, 23)); + } + + @Test(expected = RuntimeException.class) + public void testAddUnsupported() { + TestRootNode node = createRoot(AddNodeFactory.getInstance()); + executeWith(node, new Object(), new Object()); + } + + @NodeChildren({@NodeChild("left"), @NodeChild("right")}) + abstract static class BinaryNode extends ValueNode { + } + + abstract static class AddNode extends BinaryNode { + + @Specialization + int add(int left, int right) { + return left + right; + } + + @Generic + Object add(Object left, Object right) { + return convertDouble(left) + convertDouble(right); + } + + static double convertDouble(Object value) { + if (value instanceof Number) { + return ((Number) value).doubleValue(); + } else if (value instanceof String) { + return Double.parseDouble((String) value); + } + throw new RuntimeException("Invalid datatype"); + } + + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.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/ExecuteEvaluatedTest.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,107 @@ +/* + * 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 org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.DoubleEvaluatedNodeFactory; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.EvaluatedNodeFactory; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseDoubleEvaluatedNodeFactory; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseEvaluatedNodeFactory; +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; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class ExecuteEvaluatedTest { + + @Test + public void testSingleEvaluated() { + ArgumentNode arg0 = new ArgumentNode(0); + CallTarget callTarget = TestHelper.createCallTarget(UseEvaluatedNodeFactory.create(arg0, EvaluatedNodeFactory.create(null))); + + Assert.assertEquals(43, callTarget.call(new TestArguments(42))); + Assert.assertEquals(1, arg0.getInvocationCount()); + } + + @NodeChild("exp") + abstract static class EvaluatedNode extends ValueNode { + + @Specialization + int doExecuteWith(int exp) { + return exp + 1; + } + + public abstract Object executeEvaluated(VirtualFrame frame, Object targetValue); + + public abstract int executeIntEvaluated(VirtualFrame frame, Object targetValue) throws UnexpectedResultException; + } + + @NodeChildren({@NodeChild("exp0"), @NodeChild(value = "exp1", type = EvaluatedNode.class, executeWith = "exp0")}) + abstract static class UseEvaluatedNode extends ValueNode { + + @Specialization + int call(int exp0, int exp1) { + Assert.assertEquals(exp0 + 1, exp1); + return exp1; + } + } + + @Test + public void testDoubleEvaluated() { + ArgumentNode arg0 = new ArgumentNode(0); + ArgumentNode arg1 = new ArgumentNode(1); + CallTarget callTarget = TestHelper.createCallTarget(UseDoubleEvaluatedNodeFactory.create(arg0, arg1, DoubleEvaluatedNodeFactory.create(null, null))); + + Assert.assertEquals(85, callTarget.call(new TestArguments(42, 43))); + Assert.assertEquals(1, arg0.getInvocationCount()); + Assert.assertEquals(1, arg1.getInvocationCount()); + } + + @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1")}) + abstract static class DoubleEvaluatedNode extends ValueNode { + + @Specialization + int doExecuteWith(int exp0, int exp1) { + return exp0 + exp1; + } + + public abstract Object executeEvaluated(VirtualFrame frame, Object exp0, Object exp1); + + public abstract int executeIntEvaluated(VirtualFrame frame, Object exp0, Object exp1) throws UnexpectedResultException; + } + + @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1"), @NodeChild(value = "exp2", type = DoubleEvaluatedNode.class, executeWith = {"exp0", "exp1"})}) + abstract static class UseDoubleEvaluatedNode extends ValueNode { + + @Specialization + int call(int exp0, int exp1, int exp2) { + Assert.assertEquals(exp0 + exp1, exp2); + return exp2; + } + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.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/GuardsTest.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,110 @@ +/* + * 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.GuardsTestFactory.GlobalFlagGuardFactory; +import com.oracle.truffle.api.dsl.test.GuardsTestFactory.InvocationGuardFactory; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; + +@SuppressWarnings("unused") +public class GuardsTest { + + private static final Object NULL = new Object(); + + @Test + public void testGuardInvocations() { + TestRootNode root = createRoot(InvocationGuardFactory.getInstance()); + + assertEquals(Integer.MAX_VALUE, executeWith(root, Integer.MAX_VALUE - 1, 1)); + assertEquals(1, InvocationGuard.specializedInvocations); + assertEquals(0, InvocationGuard.genericInvocations); + + assertEquals(42, executeWith(root, Integer.MAX_VALUE, 1)); + assertEquals(1, InvocationGuard.specializedInvocations); + assertEquals(1, InvocationGuard.genericInvocations); + } + + @NodeChildren({@NodeChild("value0"), @NodeChild("value1")}) + public abstract static class InvocationGuard extends ValueNode { + + static int specializedInvocations = 0; + static int genericInvocations = 0; + + boolean guard(int value0, int value1) { + return value0 != Integer.MAX_VALUE; + } + + @Specialization(guards = "guard") + int doSpecialized(int value0, int value1) { + specializedInvocations++; + return value0 + value1; + } + + @Generic + int doGeneric(Object value0, Object value1) { + genericInvocations++; + return 42; // the generic answer to all questions + } + } + + @Test + public void testGuardGlobal() { + TestRootNode root = createRoot(GlobalFlagGuardFactory.getInstance()); + + assertEquals(42, executeWith(root, NULL)); + + GlobalFlagGuard.globalFlag = true; + assertEquals(41, executeWith(root, NULL)); + + GlobalFlagGuard.globalFlag = false; + assertEquals(42, executeWith(root, NULL)); + } + + @NodeChild("expression") + public abstract static class GlobalFlagGuard extends ValueNode { + + static boolean globalFlag = false; + + static boolean globalFlagGuard() { + return globalFlag; + } + + @Specialization(guards = "globalFlagGuard") + int doSpecialized(Object value0) { + return 41; + } + + @Generic + int doGeneric(Object value0) { + return 42; // the generic answer to all questions + } + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeContainerTest.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/NodeContainerTest.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,186 @@ +/* + * 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)); + } + + @NodeContainer(BuiltinNode.class) + static class Str { + + 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) + abstract static class BuiltinNode extends ValueNode { + + protected final Context context; + + public BuiltinNode(BuiltinNode node) { + this(node.context); + } + + public BuiltinNode(Context context) { + this.context = context; + } + + public Context getContext() { + return context; + } + } + + static class Context { + + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.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/PolymorphicTest.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,123 @@ +/* + * 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.BinaryNodeTest.BinaryNode; +import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Node1Factory; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeInfo.Kind; + +public class PolymorphicTest { + + @Test + public void testJustSpecialize() { + TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); + assertEquals("(int,int)", executeWith(node, 42, 42)); + assertEquals("(boolean,boolean)", executeWith(node, false, false)); + assertEquals("(int,boolean)", executeWith(node, 42, false)); + assertEquals("(boolean,int)", executeWith(node, false, 42)); + assertEquals(Kind.SPECIALIZED, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); + } + + @Test + public void testPolymorphic2() { + TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); + assertEquals("(int,boolean)", executeWith(node, 42, false)); + assertEquals("(int,int)", executeWith(node, 42, 42)); + assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); + } + + @Test + public void testPolymorphic3() { + TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); + assertEquals("(int,boolean)", executeWith(node, 42, false)); + assertEquals("(boolean,boolean)", executeWith(node, true, false)); + assertEquals("(int,int)", executeWith(node, 42, 42)); + assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); + } + + @Test + public void testGenericLimitReached() { + TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); + assertEquals("(boolean,int)", executeWith(node, false, 42)); + assertEquals("(int,boolean)", executeWith(node, 42, false)); + assertEquals("(boolean,boolean)", executeWith(node, true, false)); + assertEquals("(int,int)", executeWith(node, 42, 42)); + assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); + } + + @Test + public void testGenericInitial() { + TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); + assertEquals("(generic,generic)", executeWith(node, "", "")); + assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); + } + + @Test + public void testGenericPolymorphic() { + TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); + assertEquals("(boolean,int)", executeWith(node, false, 42)); + assertEquals("(int,boolean)", executeWith(node, 42, false)); + assertEquals("(generic,generic)", executeWith(node, "", "")); + assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); + } + + @SuppressWarnings("unused") + @PolymorphicLimit(3) + abstract static class Node1 extends BinaryNode { + + @Specialization(order = 1) + String add(int left, int right) { + return "(int,int)"; + } + + @Specialization(order = 2) + String add(boolean left, boolean right) { + return "(boolean,boolean)"; + } + + @Specialization(order = 3) + String add(int left, boolean right) { + return "(int,boolean)"; + } + + @Specialization(order = 4) + String add(boolean left, int right) { + return "(boolean,int)"; + } + + @Generic + String add(Object left, Object right) { + return "(generic,generic)"; + } + + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.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/TestHelper.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2012, 2013, 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 java.util.*; + +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; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; + +/** + * Utility class to provide some test helper functions. + */ +class TestHelper { + + private static ArgumentNode[] arguments(int count) { + ArgumentNode[] nodes = new ArgumentNode[count]; + for (int i = 0; i < nodes.length; i++) { + nodes[i] = new ArgumentNode(i); + } + return nodes; + } + + static E createNode(NodeFactory factory, Object... constants) { + ArgumentNode[] argumentNodes = arguments(factory.getExecutionSignature().size()); + + List argumentList = new ArrayList<>(); + argumentList.addAll(Arrays.asList(constants)); + if (ChildrenNode.class.isAssignableFrom(factory.getNodeClass()) || BuiltinNode.class.isAssignableFrom(factory.getNodeClass())) { + argumentList.add(argumentNodes); + } else { + argumentList.addAll(Arrays.asList(argumentNodes)); + } + return factory.createNode(argumentList.toArray(new Object[argumentList.size()])); + } + + static TestRootNode createRoot(NodeFactory factory, Object... constants) { + return new TestRootNode<>(createNode(factory, constants)); + } + + static CallTarget createCallTarget(ValueNode node) { + return createCallTarget(new TestRootNode<>(node)); + } + + static CallTarget createCallTarget(TestRootNode node) { + return Truffle.getRuntime().createCallTarget(node); + } + + static Object executeWith(TestRootNode node, Object... values) { + return createCallTarget(node).call(new TestArguments(values)); + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.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/TypeSystemTest.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2012, 2013, 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 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, Object[].class}) + static class SimpleTypes { + } + + @TypeSystemReference(SimpleTypes.class) + public abstract static class ValueNode extends Node { + + public int executeInt(VirtualFrame frame) throws UnexpectedResultException { + 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)); + } + + public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException { + return SimpleTypesGen.SIMPLETYPES.expectBoolean(execute(frame)); + } + + public Object[] executeIntArray(VirtualFrame frame) throws UnexpectedResultException { + return SimpleTypesGen.SIMPLETYPES.expectObjectArray(execute(frame)); + } + + public abstract Object execute(VirtualFrame frame); + + @Override + public ValueNode copy() { + return (ValueNode) super.copy(); + } + } + + @NodeChild(value = "children", type = ValueNode[].class) + public abstract static class ChildrenNode extends ValueNode { + + } + + @TypeSystemReference(SimpleTypes.class) + public static class TestRootNode extends RootNode { + + @Child private E node; + + public TestRootNode(E node) { + this.node = adoptChild(node); + } + + @Override + public Object execute(VirtualFrame frame) { + return node.execute(frame); + } + + public E getNode() { + return node; + } + } + + public static class TestArguments extends Arguments { + + private final Object[] values; + + public TestArguments(Object... values) { + this.values = values; + } + + public Object[] getValues() { + return values; + } + + public Object get(int index) { + return values[index]; + } + + } + + public static class ArgumentNode extends ValueNode { + + private int invocationCount; + final int index; + + public ArgumentNode(int index) { + this.index = index; + } + + public int getInvocationCount() { + return invocationCount; + } + + @Override + public Object execute(VirtualFrame frame) { + invocationCount++; + return frame.getArguments(TestArguments.class).get(index); + } + + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/package-info.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/package-info.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,50 @@ +/* + * 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. + */ +/** + *

This package contains basic tests of the Truffle-Source-Code-Generation (short Codegen) API and serves at the same + * time as an introduction to the Codegen API for language implementors. Every test gives an example on how to use the construct explained in the class description.

+ * + *

+ * This API relies heavily on the concepts described in com.oracle.truffle.api.test. We assume that the + * reader is already familiarized with those concepts. + *

+ * + *

+ * TODO general description + *

+ * + *

+ * This introduction to Codegen contains items in the following recommended order: + * + * Prerequisites: + * + * + *

    + *
  • 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}
  • + *
+ *

+ * + */ +package com.oracle.truffle.api.dsl.test; + diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/CreateCast.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/CreateCast.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,38 @@ +/* + * 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; + +import java.lang.annotation.*; + +import com.oracle.truffle.api.nodes.*; + +/** + * Specifies a factory method that creates a {@link Node} which is used to cast this child. + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface CreateCast { + + String[] value(); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/GeneratedBy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/GeneratedBy.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,38 @@ +/* + * 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; + +import java.lang.annotation.*; + +/** + * Marks a type to be generated by another class or a method. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface GeneratedBy { + + Class value(); + + String methodName() default ""; + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Generic.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Generic.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,34 @@ +/* + * 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; + +import java.lang.annotation.*; + +/** + * + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface Generic { + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,38 @@ +/* + * 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; + +import java.lang.annotation.*; + +/** + * Declares one or multiple assumptions for use inside a source code generation enabled node. + * Declared assumptions must be passed to the {@link NodeFactory#createNode(Object...)} method as + * parameters. + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE}) +public @interface NodeAssumptions { + + String[] value(); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeChild.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeChild.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,51 @@ +/* + * 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; + +import java.lang.annotation.*; + +import com.oracle.truffle.api.nodes.*; + +/** + * A {@link NodeChild} element defines an executable child for the enclosing {@link Node}. A + * {@link Node} contains multiple {@link NodeChildren} specified in linear execution order. + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE}) +public @interface NodeChild { + + String value() default ""; + + Class type() default Node.class; + + /** + * The {@link #executeWith()} property allows a node to pass the result of one child's + * executable as an input to another child's executable. These referenced children must be + * defined before the current node in the execution order. The current node {@link #type()} + * attribute must be set to a {@link Node} which supports the evaluated execution with the + * number of {@link #executeWith()} arguments that are defined. For example if this child is + * executed with one argument, the {@link #type()} attribute must define a node which publicly + * declares a method with the signature Object execute*(VirtualFrame, Object). + */ + String[] executeWith() default {}; +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeChildren.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeChildren.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE}) +public @interface NodeChildren { + + NodeChild[] value() default {}; + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeContainer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeContainer.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,42 @@ +/* + * 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; + +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 f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeFactory.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,73 @@ +/* + * 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; + +import java.util.*; + +import com.oracle.truffle.api.nodes.*; + +/** + * Enables the dynamic creation of generated nodes. It provides an convenient way to instantiate + * generated node classes without using reflection. + */ +public interface NodeFactory { + + /** + * Instantiates the node using the arguments array. The arguments length and types must suffice + * one of the returned signatures in {@link #getNodeSignatures()}. If the arguments array does + * not suffice one of the node signatures an {@link IllegalArgumentException} is thrown. + * + * @param arguments the argument values + * @return the instantiated node + * @throws IllegalArgumentException + */ + T createNode(Object... arguments); + + /** + * Instantiates a new generic variant of the node. This is an optional method and throws an + * {@link UnsupportedOperationException} if not supported. + * + * @param thisNode the current node + * @return the specialized node + */ + T createNodeGeneric(T thisNode); + + /** + * Returns the node class that will get created by {@link #createNode(Object...)}. The node + * class does not match exactly to the instantiated object but they are guaranteed to be + * assignable. + */ + Class getNodeClass(); + + /** + * Returns a list of signatures that can be used to invoke {@link #createNode(Object...)}. + */ + List>> getNodeSignatures(); + + /** + * Returns a list of children that will be executed by the created node. This is useful for base + * nodes that can execute a variable amount of nodes. + */ + List> getExecutionSignature(); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeId.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeId.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface NodeId { + + String value(); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/PolymorphicLimit.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/PolymorphicLimit.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,34 @@ +/* + * 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; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE}) +public @interface PolymorphicLimit { + + /** Specifies the maximum polymorphic cache depth until it falls back to the generic case. */ + int value(); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ShortCircuit.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ShortCircuit.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface ShortCircuit { + + String value(); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,46 @@ +/* + * 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; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface Specialization { + + int DEFAULT_ORDER = -1; + + int order() default DEFAULT_ORDER; + + Class[] rewriteOn() default {}; + + String[] guards() default {}; + + /** + * Defines the assumptions to check for this specialization. When the specialization method is + * invoked it is guaranteed that the assigned assumptions still hold. To declare assumptions use + * the {@link NodeAssumptions} annotation at class level. + */ + String[] assumptions() default {}; + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/SpecializationListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/SpecializationListener.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,30 @@ +/* + * 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; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface SpecializationListener { +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCast.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCast.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,31 @@ +/* + * 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; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface TypeCast { + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCheck.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCheck.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,80 @@ +/* + * 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; + +import java.lang.annotation.*; + +/** + *

+ * Provides a way to define a custom type check for a defined type. The name of the annotated method + * must fit to the pattern is${typeName} (eg. isInteger), where ${typeName} must be a valid type + * defined in the parent {@link TypeSystem}. The annotated method must have exactly one argument + * where the type of the argument is the generic type {@link Object} or a more specific one from the + * {@link TypeSystem}. You can define multiple overloaded {@link TypeCheck} methods for the same + * type. This can be used to reduce the boxing overhead in type conversions. + *

+ * + *

+ * By default the system generates type checks for all types in the parent {@link TypeSystem} which + * look like the follows: + * + *

+ * {@literal @}TypeCheck
+ * boolean is${typeName}(Object value) {
+ *         return value instanceof ${typeName};
+ * }
+ * 
+ * + *

+ * + * Example: + *

+ * A type check for BigInteger with one overloaded optimized variant to reduce boxing. + *

+ * + *
+ * 
+ * 
+ * {@literal @}TypeSystem(types = {int.class, BigInteger.class, String.class}, nodeBaseClass = TypedNode.class)
+ * public abstract class Types {
+ * 
+ *     {@literal @}TypeCheck
+ *     public boolean isBigInteger(Object value) {
+ *         return value instanceof Integer || value instanceof BigInteger;
+ *     }
+ * 
+ *     {@literal @}TypeCheck
+ *     public boolean isBigInteger(int value) {
+ *         return true;
+ *     }
+ * 
+ * }
+ * 
+ * + * + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface TypeCheck { + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystem.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystem.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,89 @@ +/* + * 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; + +import java.lang.annotation.*; + +import com.oracle.truffle.api.nodes.*; + +/** + *

+ * Each {@link Node} has one {@link TypeSystem} at its root to define the types that can be used + * throughout the system. Multiple {@link TypeSystem}s are allowed, but they cannot be mixed inside + * a single {@link Node} hierarchy. A {@link TypeSystem} defines a list of types as its child + * elements, in which every type precedes its super types.The latter condition ensures that the most + * concrete type is found first when searching the list sequentially for the type of a given generic + * value. + *

+ * + *

+ * Each {@link #value()} is represented as a java type. A type can specify two annotations: + * {@link TypeCheck} and {@link TypeCast}. The {@link TypeCheck} checks whether a given generic + * value matches to the current type. The {@link TypeCast} casts a generic type value to the current + * type. If the {@link TypeCheck} and {@link TypeCast} annotations are not declared in the + * {@link TypeSystem} the a default implementation is provided. The default implementation of + * {@link TypeCheck} returns true only on an exact type match and {@link TypeCast} is + * only a cast to this type. Specified methods with {@link TypeCheck} and {@link TypeCast} may be + * used to extend the definition of a type in the language. In our example, the + * isInteger and asInteger methods are defined in a way so that they + * accept also {@link Integer} values, implicitly converting them to {@link Double} . This example + * points out how we express implicit type conversions. + *

+ * + *

+ * Example: The {@link TypeSystem} contains the types {@link Boolean}, {@link Integer}, and + * {@link Double}. The type {@link Object} is always used implicitly as the generic type represent + * all values. + * + *

+ * 
+ * {@literal @}TypeSystem(types = {boolean.class, int.class, double.class})
+ * public abstract class ExampleTypeSystem {
+ * 
+ *     {@literal @}TypeCheck
+ *     public boolean isInteger(Object value) {
+ *         return value instanceof Integer || value instanceof Double;
+ *     }
+ * 
+ *     {@literal @}TypeCast
+ *     public double asInteger(Object value) {
+ *         return ((Number)value).doubleValue();
+ *     }
+ * }
+ * 
+ * + *

+ * + * @see TypeCast + * @see TypeCheck + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE}) +public @interface TypeSystem { + + /** + * The list of types as child elements of the {@link TypeSystem}. Each precedes its super type. + */ + Class[] value(); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystemReference.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystemReference.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,43 @@ +/* + * 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; + +import java.lang.annotation.*; + +import com.oracle.truffle.api.nodes.*; + +/** + * References a {@link TypeSystem} on a node. Must be applied on a {@link Node} class. At least one + * {@link TypeSystem} must be referenced in a {@link Node}'s type hierarchy. + * + * @see TypeSystem + * @see Node + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE}) +public @interface TypeSystemReference { + + /** The {@link TypeSystem} java type. */ + Class value(); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/META-INF/services/javax.annotation.processing.Processor --- a/graal/com.oracle.truffle.codegen.processor/src/META-INF/services/javax.annotation.processing.Processor Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -com.oracle.truffle.codegen.processor.TruffleProcessor diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +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.codegen.processor; - -import java.lang.annotation.*; -import java.util.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.tools.Diagnostic.Kind; - -import com.oracle.truffle.codegen.processor.template.*; - -/** - * THIS IS NOT PUBLIC API. - */ -public abstract class AbstractParser { - - protected final ProcessorContext context; - protected final ProcessingEnvironment processingEnv; - protected RoundEnvironment roundEnv; - - protected final Log log; - - public AbstractParser(ProcessorContext c) { - this.context = c; - this.processingEnv = c.getEnvironment(); - this.log = c.getLog(); - } - - public final M parse(RoundEnvironment env, Element element) { - this.roundEnv = env; - M model = null; - try { - AnnotationMirror mirror = null; - if (getAnnotationType() != null) { - mirror = Utils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType()); - } - - if (!context.getTruffleTypes().verify(context, element, mirror)) { - return null; - } - model = parse(element, mirror); - if (model == null) { - return null; - } - - model.emitMessages((TypeElement) element, log); - return filterErrorElements(model); - } catch (CompileErrorException e) { - log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage()); - return null; - } finally { - this.roundEnv = null; - } - } - - protected M filterErrorElements(M model) { - return model.hasErrors() ? null : model; - } - - protected abstract M parse(Element element, AnnotationMirror mirror); - - public abstract Class getAnnotationType(); - - public boolean isDelegateToRootDeclaredType() { - return false; - } - - public List> getAllAnnotationTypes() { - List> list = new ArrayList<>(); - if (getAnnotationType() != null) { - list.add(getAnnotationType()); - } - list.addAll(getTypeDelegatedAnnotationTypes()); - return list; - } - - public List> getTypeDelegatedAnnotationTypes() { - return Collections.emptyList(); - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AnnotationProcessor.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AnnotationProcessor.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +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.codegen.processor; - -import java.io.*; -import java.util.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.tools.*; - -import com.oracle.truffle.codegen.processor.ast.*; -import com.oracle.truffle.codegen.processor.codewriter.*; -import com.oracle.truffle.codegen.processor.compiler.*; -import com.oracle.truffle.codegen.processor.template.*; - -/** - * THIS IS NOT PUBLIC API. - */ -class AnnotationProcessor { - - private final AbstractParser parser; - private final CompilationUnitFactory factory; - private final ProcessorContext context; - - private final Set processedElements = new HashSet<>(); - - public AnnotationProcessor(ProcessorContext context, AbstractParser parser, CompilationUnitFactory factory) { - this.context = context; - this.parser = parser; - this.factory = factory; - } - - public AbstractParser getParser() { - return parser; - } - - public ProcessorContext getContext() { - return context; - } - - @SuppressWarnings({"unchecked"}) - public void process(RoundEnvironment env, Element element, boolean callback) { - - // since it is not guaranteed to be called only once by the compiler - // we check for already processed elements to avoid errors when writing files. - if (!callback && element instanceof TypeElement) { - String qualifiedName = Utils.getQualifiedName((TypeElement) element); - if (processedElements.contains(qualifiedName)) { - return; - } - processedElements.add(qualifiedName); - } - - TypeElement type = (TypeElement) element; - - M model = (M) context.getTemplate(type.asType(), false); - boolean firstRun = !context.containsTemplate(type); - - if (firstRun || !callback) { - context.registerTemplate(type, null); - model = parser.parse(env, element); - context.registerTemplate(type, model); - - if (model != null) { - CodeCompilationUnit unit = factory.process(null, model); - unit.setGeneratorAnnotationMirror(model.getTemplateTypeAnnotation()); - unit.setGeneratorElement(model.getTemplateType()); - - DeclaredType overrideType = (DeclaredType) context.getType(Override.class); - DeclaredType unusedType = (DeclaredType) context.getType(SuppressWarnings.class); - unit.accept(new GenerateOverrideVisitor(overrideType), null); - unit.accept(new FixWarningsVisitor(context, unusedType, overrideType), null); - - if (!callback) { - unit.accept(new CodeWriter(context.getEnvironment(), element), null); - } - } - } - } - - private static class CodeWriter extends AbstractCodeWriter { - - private final Element orignalElement; - private final ProcessingEnvironment env; - - public CodeWriter(ProcessingEnvironment env, Element originalElement) { - this.env = env; - this.orignalElement = originalElement; - } - - @Override - protected Writer createWriter(CodeTypeElement clazz) throws IOException { - JavaFileObject jfo = env.getFiler().createSourceFile(clazz.getQualifiedName(), orignalElement); - return jfo.openWriter(); - } - - @Override - protected void writeHeader() { - if (env == null) { - return; - } - String comment = CompilerFactory.getCompiler(orignalElement).getHeaderComment(env, orignalElement); - if (comment != null) { - writeLn(comment); - } - } - - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/CompileErrorException.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/CompileErrorException.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +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.codegen.processor; - -public class CompileErrorException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - public CompileErrorException(String message) { - super(message); - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +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.codegen.processor; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.tools.Diagnostic.Kind; - -import com.oracle.truffle.codegen.processor.ast.*; - -/** - * THIS IS NOT PUBLIC API. - */ -public class Log { - - public static final boolean DEBUG = false; - - private final ProcessingEnvironment processingEnv; - - public Log(ProcessingEnvironment env) { - this.processingEnv = env; - } - - public void message(Kind kind, Element element, AnnotationMirror mirror, AnnotationValue value, String format, Object... args) { - AnnotationMirror usedMirror = mirror; - Element usedElement = element; - AnnotationValue usedValue = value; - String message = String.format(format, args); - - if (element instanceof GeneratedElement) { - usedMirror = ((GeneratedElement) element).getGeneratorAnnotationMirror(); - usedElement = ((GeneratedElement) element).getGeneratorElement(); - usedValue = null; - if (usedElement != null) { - message = String.format("Element %s: %s", element, message); - } - } - processingEnv.getMessager().printMessage(kind, message, usedElement, usedMirror, usedValue); - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ProcessorContext.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ProcessorContext.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +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.codegen.processor; - -import static com.oracle.truffle.codegen.processor.Utils.*; - -import java.util.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.codegen.processor.ast.*; -import com.oracle.truffle.codegen.processor.ast.CodeTypeMirror.ArrayCodeTypeMirror; -import com.oracle.truffle.codegen.processor.template.*; - -/** - * THIS IS NOT PUBLIC API. - */ -public class ProcessorContext { - - private final ProcessingEnvironment environment; - - private final Map models = new HashMap<>(); - private final Map> generatedClasses = new HashMap<>(); - - private final ProcessCallback callback; - private final Log log; - private final TruffleTypes truffleTypes; - - public ProcessorContext(ProcessingEnvironment env, ProcessCallback callback) { - this.environment = env; - this.callback = callback; - this.log = new Log(environment); - this.truffleTypes = new TruffleTypes(this); - } - - public TruffleTypes getTruffleTypes() { - return truffleTypes; - } - - public Log getLog() { - return log; - } - - public ProcessingEnvironment getEnvironment() { - return environment; - } - - public boolean containsTemplate(TypeElement element) { - return models.containsKey(Utils.getQualifiedName(element)); - } - - public void registerTemplate(TypeElement element, Template model) { - models.put(Utils.getQualifiedName(element), model); - } - - public void registerType(TypeElement templateType, TypeMirror generatedTypeMirror) { - String templateQualifiedName = getQualifiedName(templateType); - Map simpleNameToType = generatedClasses.get(templateQualifiedName); - if (simpleNameToType == null) { - simpleNameToType = new HashMap<>(); - generatedClasses.put(templateQualifiedName, simpleNameToType); - } - String generatedSimpleName = getSimpleName(generatedTypeMirror); - simpleNameToType.put(generatedSimpleName, generatedTypeMirror); - } - - public Template getTemplate(TypeMirror templateTypeMirror, boolean invokeCallback) { - String qualifiedName = Utils.getQualifiedName(templateTypeMirror); - Template model = models.get(qualifiedName); - if (model == null && invokeCallback) { - callback.callback(Utils.fromTypeMirror(templateTypeMirror)); - model = models.get(qualifiedName); - } - return model; - } - - public TypeMirror resolveNotYetCompiledType(TypeMirror mirror, Template templateHint) { - TypeMirror resolvedType = null; - if (mirror.getKind() == TypeKind.ARRAY) { - TypeMirror originalComponentType = ((ArrayType) mirror).getComponentType(); - TypeMirror resolvedComponent = resolveNotYetCompiledType(originalComponentType, templateHint); - if (resolvedComponent != originalComponentType) { - return new ArrayCodeTypeMirror(resolvedComponent); - } - } - - if (mirror.getKind() == TypeKind.ERROR) { - Element element = ((ErrorType) mirror).asElement(); - ElementKind kind = element.getKind(); - if (kind == ElementKind.CLASS || kind == ElementKind.PARAMETER || kind == ElementKind.ENUM) { - String simpleName = element.getSimpleName().toString(); - resolvedType = findGeneratedClassBySimpleName(simpleName, templateHint); - } - } else { - resolvedType = mirror; - } - - return resolvedType; - } - - public TypeMirror findGeneratedClassBySimpleName(String simpleName, Template templateHint) { - if (templateHint == null) { - // search all - for (String qualifiedTemplateName : generatedClasses.keySet()) { - Map mirrors = generatedClasses.get(qualifiedTemplateName); - if (mirrors.get(simpleName) != null) { - return mirrors.get(simpleName); - } - } - return null; - } else { - String templateQualifiedName = getQualifiedName(templateHint.getTemplateType()); - Map simpleNameToType = generatedClasses.get(templateQualifiedName); - if (simpleNameToType == null) { - return null; - } - return simpleNameToType.get(simpleName); - } - } - - public TypeMirror getType(String className) { - TypeElement element = environment.getElementUtils().getTypeElement(className); - if (element != null) { - return element.asType(); - } - return null; - } - - public TypeMirror getType(Class element) { - TypeMirror mirror; - if (element.isPrimitive()) { - if (element == boolean.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.BOOLEAN); - } else if (element == byte.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.BYTE); - } else if (element == short.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.SHORT); - } else if (element == char.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.CHAR); - } else if (element == int.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.INT); - } else if (element == long.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.LONG); - } else if (element == float.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.FLOAT); - } else if (element == double.class) { - mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.DOUBLE); - } else if (element == void.class) { - mirror = environment.getTypeUtils().getNoType(TypeKind.VOID); - } else { - assert false; - return null; - } - } else { - TypeElement typeElement = environment.getElementUtils().getTypeElement(element.getCanonicalName()); - mirror = typeElement.asType(); - } - return mirror; - } - - public interface ProcessCallback { - - void callback(TypeElement template); - - } - - public TypeMirror reloadTypeElement(TypeElement type) { - return getType(type.getQualifiedName().toString()); - } - - public TypeMirror reloadType(TypeMirror type) { - if (type instanceof CodeTypeMirror) { - return type; - } else if (type.getKind().isPrimitive()) { - return type; - } - Types types = getEnvironment().getTypeUtils(); - - switch (type.getKind()) { - case ARRAY: - return types.getArrayType(reloadType(((ArrayType) type).getComponentType())); - case WILDCARD: - return types.getWildcardType(((WildcardType) type).getExtendsBound(), ((WildcardType) type).getSuperBound()); - case DECLARED: - return reloadTypeElement((TypeElement) (((DeclaredType) type).asElement())); - } - return type; - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,150 +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.codegen.processor; - -import java.lang.annotation.*; -import java.util.*; - -import javax.annotation.processing.*; -import javax.lang.model.*; -import javax.lang.model.element.*; -import javax.tools.Diagnostic.*; - -import com.oracle.truffle.codegen.processor.ProcessorContext.ProcessCallback; -import com.oracle.truffle.codegen.processor.node.*; -import com.oracle.truffle.codegen.processor.typesystem.*; - -/** - * THIS IS NOT PUBLIC API. - */ -// @SupportedAnnotationTypes({"com.oracle.truffle.codegen.Operation", -// "com.oracle.truffle.codegen.TypeLattice"}) -@SupportedSourceVersion(SourceVersion.RELEASE_7) -public class TruffleProcessor extends AbstractProcessor implements ProcessCallback { - - private ProcessorContext context; - private List> generators; - - private RoundEnvironment round; - - @Override - public boolean process(Set annotations, RoundEnvironment roundEnv) { - if (!roundEnv.processingOver()) { - processImpl(roundEnv); - } - return false; - } - - private void processImpl(RoundEnvironment env) { - this.round = env; - // TODO run verifications that other annotations are not processed out of scope of the - // operation or typelattice. - try { - for (AnnotationProcessor generator : getGenerators()) { - AbstractParser parser = generator.getParser(); - if (parser.getAnnotationType() != null) { - for (Element e : env.getElementsAnnotatedWith(parser.getAnnotationType())) { - processElement(env, generator, e, false); - } - } - - for (Class annotationType : parser.getTypeDelegatedAnnotationTypes()) { - for (Element e : env.getElementsAnnotatedWith(annotationType)) { - TypeElement processedType; - if (parser.isDelegateToRootDeclaredType()) { - processedType = Utils.findRootEnclosingType(e); - } else { - processedType = Utils.findNearestEnclosingType(e); - } - processElement(env, generator, processedType, false); - } - } - - } - } finally { - this.round = null; - } - } - - private static void processElement(RoundEnvironment env, AnnotationProcessor generator, Element e, boolean callback) { - try { - generator.process(env, e, callback); - } catch (Throwable e1) { - handleThrowable(generator, e1, e); - } - } - - private static void handleThrowable(AnnotationProcessor generator, Throwable t, Element e) { - String message = "Uncaught error in " + generator.getClass().getSimpleName() + " while processing " + e; - generator.getContext().getLog().message(Kind.ERROR, e, null, null, message + ": " + Utils.printException(t)); - } - - @SuppressWarnings("unchecked") - @Override - public void callback(TypeElement template) { - for (AnnotationProcessor generator : generators) { - Class annotationType = generator.getParser().getAnnotationType(); - if (annotationType != null) { - Annotation annotation = template.getAnnotation(annotationType); - if (annotation != null) { - processElement(round, generator, template, true); - } - } - } - } - - @Override - public Set getSupportedAnnotationTypes() { - Set annotations = new HashSet<>(); - List> annotationsTypes = new ArrayList<>(); - annotationsTypes.addAll(NodeParser.ANNOTATIONS); - annotationsTypes.addAll(TypeSystemParser.ANNOTATIONS); - for (Class type : annotationsTypes) { - annotations.add(type.getCanonicalName()); - } - return annotations; - } - - private List> getGenerators() { - if (generators == null && processingEnv != null) { - generators = new ArrayList<>(); - generators.add(new AnnotationProcessor<>(getContext(), new TypeSystemParser(getContext()), new TypeSystemCodeGenerator(getContext()))); - generators.add(new AnnotationProcessor<>(getContext(), new NodeParser(getContext()), new NodeCodeGenerator(getContext()))); - } - return generators; - } - - private ProcessorContext getContext() { - if (context == null) { - context = new ProcessorContext(processingEnv, this); - } - return context; - } - - @Override - public synchronized void init(ProcessingEnvironment env) { - this.processingEnv = env; - super.init(env); - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +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.codegen.processor; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.tools.Diagnostic.Kind; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.Node.Child; -import com.oracle.truffle.api.nodes.Node.Children; - -/** - * THIS IS NOT PUBLIC API. - */ -public final class TruffleTypes { - - private final TypeMirror node; - private final TypeMirror nodeArray; - private final TypeMirror unexpectedValueException; - private final TypeMirror frame; - private final TypeMirror assumption; - private final TypeMirror invalidAssumption; - private final DeclaredType childAnnotation; - private final DeclaredType childrenAnnotation; - private final DeclaredType nodeInfoAnnotation; - private final DeclaredType nodeInfoKind; - private final TypeMirror compilerDirectives; - private final TypeMirror compilerAsserts; - - private final List errors = new ArrayList<>(); - - public TruffleTypes(ProcessorContext context) { - node = getRequired(context, Node.class); - nodeArray = context.getEnvironment().getTypeUtils().getArrayType(node); - unexpectedValueException = getRequired(context, UnexpectedResultException.class); - frame = getRequired(context, VirtualFrame.class); - childAnnotation = getRequired(context, Child.class); - childrenAnnotation = getRequired(context, Children.class); - compilerDirectives = getRequired(context, CompilerDirectives.class); - compilerAsserts = getRequired(context, CompilerAsserts.class); - assumption = getRequired(context, Assumption.class); - invalidAssumption = getRequired(context, InvalidAssumptionException.class); - nodeInfoAnnotation = getRequired(context, NodeInfo.class); - nodeInfoKind = getRequired(context, NodeInfo.Kind.class); - } - - public DeclaredType getNodeInfoAnnotation() { - return nodeInfoAnnotation; - } - - public boolean verify(ProcessorContext context, Element element, AnnotationMirror mirror) { - if (errors.isEmpty()) { - return true; - } - - for (String error : errors) { - context.getLog().message(Kind.ERROR, element, mirror, null, error); - } - - return false; - } - - public DeclaredType getNodeInfoKind() { - return nodeInfoKind; - } - - private DeclaredType getRequired(ProcessorContext context, Class clazz) { - TypeMirror type = context.getType(clazz); - if (type == null) { - errors.add(String.format("Could not find required type: %s", clazz.getSimpleName())); - } - return (DeclaredType) type; - } - - public TypeMirror getInvalidAssumption() { - return invalidAssumption; - } - - public TypeMirror getAssumption() { - return assumption; - } - - public TypeMirror getCompilerDirectives() { - return compilerDirectives; - } - - public TypeMirror getNode() { - return node; - } - - public TypeMirror getNodeArray() { - return nodeArray; - } - - public TypeMirror getFrame() { - return frame; - } - - public TypeMirror getUnexpectedValueException() { - return unexpectedValueException; - } - - public DeclaredType getChildAnnotation() { - return childAnnotation; - } - - public DeclaredType getChildrenAnnotation() { - return childrenAnnotation; - } - - public TypeMirror getCompilerAsserts() { - return compilerAsserts; - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,930 +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.codegen.processor; - -import java.io.*; -import java.lang.annotation.*; -import java.util.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.codegen.processor.ast.*; -import com.oracle.truffle.codegen.processor.ast.CodeTypeMirror.DeclaredCodeTypeMirror; -import com.oracle.truffle.codegen.processor.compiler.*; - -/** - * THIS IS NOT PUBLIC API. - */ -public class Utils { - - public static ExecutableElement findExecutableElement(DeclaredType type, String name) { - List elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements()); - for (ExecutableElement executableElement : elements) { - if (executableElement.getSimpleName().toString().equals(name)) { - return executableElement; - } - } - return null; - } - - public static VariableElement findVariableElement(DeclaredType type, String name) { - List elements = ElementFilter.fieldsIn(type.asElement().getEnclosedElements()); - for (VariableElement variableElement : elements) { - if (variableElement.getSimpleName().toString().equals(name)) { - return variableElement; - } - } - return null; - } - - public static String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { - if (method instanceof CodeExecutableElement) { - return ((CodeExecutableElement) method).getBody(); - } else { - return CompilerFactory.getCompiler(method).getMethodBody(env, method); - } - } - - public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) { - TypeMirror boxedType = primitiveType; - if (boxedType.getKind().isPrimitive()) { - boxedType = context.getEnvironment().getTypeUtils().boxedClass((PrimitiveType) boxedType).asType(); - } - return boxedType; - } - - public static List asTypeMirrors(List elements) { - List types = new ArrayList<>(elements.size()); - for (Element element : elements) { - types.add(element.asType()); - } - return types; - } - - public static DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) { - return new DeclaredCodeTypeMirror(typeElem, Arrays.asList(typeArgs)); - } - - public static List collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element, - Class annotationClass) { - List result = new ArrayList<>(); - if (markerAnnotation != null) { - result.addAll(Utils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName)); - } - AnnotationMirror explicit = Utils.findAnnotationMirror(context.getEnvironment(), element, annotationClass); - if (explicit != null) { - result.add(explicit); - } - return result; - } - - public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror[] types) { - if (types.length == 0) { - return context.getType(Object.class); - } - TypeMirror prev = types[0]; - for (int i = 1; i < types.length; i++) { - prev = getCommonSuperType(context, prev, types[i]); - } - return prev; - } - - public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror type1, TypeMirror type2) { - if (typeEquals(type1, type2)) { - return type1; - } - TypeElement element1 = fromTypeMirror(type1); - TypeElement element2 = fromTypeMirror(type2); - if (element1 == null || element2 == null) { - return context.getType(Object.class); - } - - List element1Types = getDirectSuperTypes(element1); - element1Types.add(0, element1); - List element2Types = getDirectSuperTypes(element2); - element2Types.add(0, element2); - - for (TypeElement superType1 : element1Types) { - for (TypeElement superType2 : element2Types) { - if (typeEquals(superType1.asType(), superType2.asType())) { - return superType2.asType(); - } - } - } - return context.getType(Object.class); - } - - public static String getReadableSignature(ExecutableElement method) { - // TODO toString does not guarantee a good signature - return method.toString(); - } - - public static boolean hasError(TypeMirror mirror) { - switch (mirror.getKind()) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FLOAT: - case INT: - case SHORT: - case LONG: - case DECLARED: - case VOID: - case TYPEVAR: - return false; - case ARRAY: - return hasError(((ArrayType) mirror).getComponentType()); - case ERROR: - return true; - default: - throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); - } - } - - public static boolean isAssignable(ProcessorContext context, TypeMirror from, TypeMirror to) { - if (!(from instanceof CodeTypeMirror) && !(to instanceof CodeTypeMirror)) { - return context.getEnvironment().getTypeUtils().isAssignable(context.reloadType(from), context.reloadType(to)); - } else { - return isAssignableImpl(context, from, to); - } - } - - private static boolean isAssignableImpl(ProcessorContext context, TypeMirror from, TypeMirror to) { - // JLS 5.1.1 identity conversion - if (Utils.typeEquals(from, to)) { - return true; - } - - // JLS 5.1.2 widening primitives - if (Utils.isPrimitive(from) && Utils.isPrimitive(to)) { - TypeKind fromKind = from.getKind(); - TypeKind toKind = to.getKind(); - switch (fromKind) { - case BYTE: - switch (toKind) { - case SHORT: - case INT: - case LONG: - case FLOAT: - case DOUBLE: - return true; - } - break; - case SHORT: - switch (toKind) { - case INT: - case LONG: - case FLOAT: - case DOUBLE: - return true; - } - break; - case CHAR: - switch (toKind) { - case INT: - case LONG: - case FLOAT: - case DOUBLE: - return true; - } - break; - case INT: - switch (toKind) { - case LONG: - case FLOAT: - case DOUBLE: - return true; - } - break; - case LONG: - switch (toKind) { - case FLOAT: - case DOUBLE: - return true; - } - break; - case FLOAT: - switch (toKind) { - case DOUBLE: - return true; - } - break; - - } - return false; - } else if (Utils.isPrimitive(from) || Utils.isPrimitive(to)) { - return false; - } - - if (from instanceof ArrayType && to instanceof ArrayType) { - return isAssignable(context, ((ArrayType) from).getComponentType(), ((ArrayType) to).getComponentType()); - } - - TypeElement fromType = Utils.fromTypeMirror(from); - TypeElement toType = Utils.fromTypeMirror(to); - if (fromType == null || toType == null) { - return false; - } - // JLS 5.1.6 narrowing reference conversion - - List superTypes = Utils.getSuperTypes(fromType); - for (TypeElement superType : superTypes) { - if (Utils.typeEquals(superType.asType(), to)) { - return true; - } - } - - // TODO more spec - return false; - } - - public static Set modifiers(Modifier... modifier) { - return new LinkedHashSet<>(Arrays.asList(modifier)); - } - - public static String getTypeId(TypeMirror mirror) { - switch (mirror.getKind()) { - case BOOLEAN: - return "Boolean"; - case BYTE: - return "Byte"; - case CHAR: - return "Char"; - case DOUBLE: - return "Double"; - case FLOAT: - return "Float"; - case SHORT: - return "Short"; - case INT: - return "Int"; - case LONG: - return "Long"; - case DECLARED: - return ((DeclaredType) mirror).asElement().getSimpleName().toString(); - case ARRAY: - return getTypeId(((ArrayType) mirror).getComponentType()) + "Array"; - case VOID: - return "Void"; - case WILDCARD: - StringBuilder b = new StringBuilder(); - WildcardType type = (WildcardType) mirror; - if (type.getExtendsBound() != null) { - b.append("Extends").append(getTypeId(type.getExtendsBound())); - } else if (type.getSuperBound() != null) { - b.append("Super").append(getTypeId(type.getExtendsBound())); - } - return b.toString(); - case TYPEVAR: - return "Any"; - case ERROR: - throw new CompileErrorException("Type error " + mirror); - default: - throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); - } - } - - public static String getSimpleName(TypeElement element) { - return getSimpleName(element.asType()); - } - - public static String getSimpleName(TypeMirror mirror) { - switch (mirror.getKind()) { - case BOOLEAN: - return "boolean"; - case BYTE: - return "byte"; - case CHAR: - return "char"; - case DOUBLE: - return "double"; - case FLOAT: - return "float"; - case SHORT: - return "short"; - case INT: - return "int"; - case LONG: - return "long"; - case DECLARED: - return getDeclaredName((DeclaredType) mirror); - case ARRAY: - return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]"; - case VOID: - return "void"; - case WILDCARD: - return getWildcardName((WildcardType) mirror); - case TYPEVAR: - return "?"; - case ERROR: - throw new CompileErrorException("Type error " + mirror); - default: - throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); - } - } - - private static String getWildcardName(WildcardType type) { - StringBuilder b = new StringBuilder(); - if (type.getExtendsBound() != null) { - b.append("? extends ").append(getSimpleName(type.getExtendsBound())); - } else if (type.getSuperBound() != null) { - b.append("? super ").append(getSimpleName(type.getExtendsBound())); - } - return b.toString(); - } - - private static String getDeclaredName(DeclaredType element) { - String simpleName = element.asElement().getSimpleName().toString(); - - if (element.getTypeArguments().size() == 0) { - return simpleName; - } - - StringBuilder b = new StringBuilder(simpleName); - b.append("<"); - if (element.getTypeArguments().size() > 0) { - for (int i = 0; i < element.getTypeArguments().size(); i++) { - b.append(getSimpleName(element.getTypeArguments().get(i))); - if (i < element.getTypeArguments().size() - 1) { - b.append(", "); - } - } - } - b.append(">"); - return b.toString(); - } - - public static String getQualifiedName(TypeElement element) { - return element.getQualifiedName().toString(); - } - - public static String getQualifiedName(TypeMirror mirror) { - switch (mirror.getKind()) { - case BOOLEAN: - return "boolean"; - case BYTE: - return "byte"; - case CHAR: - return "char"; - case DOUBLE: - return "double"; - case SHORT: - return "short"; - case FLOAT: - return "float"; - case INT: - return "int"; - case LONG: - return "long"; - case DECLARED: - return getQualifiedName(fromTypeMirror(mirror)); - case ARRAY: - return getQualifiedName(((ArrayType) mirror).getComponentType()); - case VOID: - return "void"; - case TYPEVAR: - return getSimpleName(mirror); - case ERROR: - throw new CompileErrorException("Type error " + mirror); - case NONE: - return "$none"; - default: - throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror); - } - } - - public static boolean isVoid(TypeMirror mirror) { - return mirror.getKind() == TypeKind.VOID; - } - - public static boolean isPrimitive(TypeMirror mirror) { - return mirror.getKind().isPrimitive(); - } - - public static boolean isPrimitiveOrVoid(TypeMirror mirror) { - return isPrimitive(mirror) || isVoid(mirror); - } - - public static List getQualifiedSuperTypeNames(TypeElement element) { - List types = getSuperTypes(element); - List qualifiedNames = new ArrayList<>(); - for (TypeElement type : types) { - qualifiedNames.add(getQualifiedName(type)); - } - return qualifiedNames; - } - - public static List getDeclaredTypes(TypeElement element) { - return ElementFilter.typesIn(element.getEnclosedElements()); - } - - public static VariableElement findDeclaredField(TypeMirror type, String singletonName) { - List elements = ElementFilter.fieldsIn(fromTypeMirror(type).getEnclosedElements()); - for (VariableElement var : elements) { - if (var.getSimpleName().toString().equals(singletonName)) { - return var; - } - } - return null; - } - - public static TypeElement findRootEnclosingType(Element element) { - List elements = getElementHierarchy(element); - - for (int i = elements.size() - 1; i >= 0; i--) { - if (elements.get(i).getKind().isClass()) { - return (TypeElement) elements.get(i); - } - } - - return null; - } - - public static List getElementHierarchy(Element e) { - List elements = new ArrayList<>(); - elements.add(e); - - Element enclosing = e.getEnclosingElement(); - while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) { - elements.add(enclosing); - enclosing = enclosing.getEnclosingElement(); - } - if (enclosing != null) { - elements.add(enclosing); - } - return elements; - } - - public static TypeElement findNearestEnclosingType(Element element) { - List elements = getElementHierarchy(element); - for (Element e : elements) { - if (e.getKind().isClass()) { - return (TypeElement) e; - } - } - return null; - } - - public static List getDirectSuperTypes(TypeElement element) { - List types = new ArrayList<>(); - if (element.getSuperclass() != null) { - TypeElement superElement = fromTypeMirror(element.getSuperclass()); - if (superElement != null) { - types.add(superElement); - types.addAll(getDirectSuperTypes(superElement)); - } - } - - return types; - } - - public static List getSuperTypes(TypeElement element) { - List types = new ArrayList<>(); - List superTypes = null; - List superInterfaces = null; - if (element.getSuperclass() != null) { - TypeElement superElement = fromTypeMirror(element.getSuperclass()); - if (superElement != null) { - types.add(superElement); - superTypes = getSuperTypes(superElement); - } - } - for (TypeMirror interfaceMirror : element.getInterfaces()) { - TypeElement interfaceElement = fromTypeMirror(interfaceMirror); - if (interfaceElement != null) { - types.add(interfaceElement); - superInterfaces = getSuperTypes(interfaceElement); - } - } - - if (superTypes != null) { - types.addAll(superTypes); - } - - if (superInterfaces != null) { - types.addAll(superInterfaces); - } - - return types; - } - - public static String getPackageName(TypeElement element) { - return findPackageElement(element).getQualifiedName().toString(); - } - - public static String getPackageName(TypeMirror mirror) { - switch (mirror.getKind()) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FLOAT: - case SHORT: - case INT: - case LONG: - case VOID: - case TYPEVAR: - return null; - case DECLARED: - PackageElement pack = findPackageElement(fromTypeMirror(mirror)); - if (pack == null) { - throw new IllegalArgumentException("No package element found for declared type " + getSimpleName(mirror)); - } - return pack.getQualifiedName().toString(); - case ARRAY: - return getSimpleName(((ArrayType) mirror).getComponentType()); - default: - throw new RuntimeException("Unknown type specified " + mirror.getKind()); - } - } - - public static String createConstantName(String simpleName) { - // TODO use camel case to produce underscores. - return simpleName.toString().toUpperCase(); - } - - public static TypeElement fromTypeMirror(TypeMirror mirror) { - switch (mirror.getKind()) { - case DECLARED: - return (TypeElement) ((DeclaredType) mirror).asElement(); - case ARRAY: - return fromTypeMirror(((ArrayType) mirror).getComponentType()); - default: - return null; - } - } - - @SuppressWarnings("unchecked") - public static List getAnnotationValueList(Class expectedListType, AnnotationMirror mirror, String name) { - List values = getAnnotationValue(List.class, mirror, name); - List result = new ArrayList<>(); - - if (values != null) { - for (AnnotationValue value : values) { - T annotationValue = resolveAnnotationValue(expectedListType, value); - if (annotationValue != null) { - result.add(annotationValue); - } - } - } - return result; - } - - public static T getAnnotationValue(Class expectedType, AnnotationMirror mirror, String name) { - return resolveAnnotationValue(expectedType, getAnnotationValue(mirror, name)); - } - - @SuppressWarnings({"unchecked"}) - private static T resolveAnnotationValue(Class expectedType, AnnotationValue value) { - if (value == null) { - return null; - } - - Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null); - if (unboxedValue != null) { - if (expectedType == TypeMirror.class && unboxedValue instanceof String) { - return null; - } - if (!expectedType.isAssignableFrom(unboxedValue.getClass())) { - throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName()); - } - } - return (T) unboxedValue; - } - - public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) { - ExecutableElement valueMethod = null; - for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) { - if (method.getSimpleName().toString().equals(name)) { - valueMethod = method; - break; - } - } - - if (valueMethod == null) { - return null; - } - - AnnotationValue value = mirror.getElementValues().get(valueMethod); - if (value == null) { - value = valueMethod.getDefaultValue(); - } - - return value; - } - - private static class AnnotationValueVisitorImpl extends AbstractAnnotationValueVisitor7 { - - @Override - public Object visitBoolean(boolean b, Void p) { - return Boolean.valueOf(b); - } - - @Override - public Object visitByte(byte b, Void p) { - return Byte.valueOf(b); - } - - @Override - public Object visitChar(char c, Void p) { - return c; - } - - @Override - public Object visitDouble(double d, Void p) { - return d; - } - - @Override - public Object visitFloat(float f, Void p) { - return f; - } - - @Override - public Object visitInt(int i, Void p) { - return i; - } - - @Override - public Object visitLong(long i, Void p) { - return i; - } - - @Override - public Object visitShort(short s, Void p) { - return s; - } - - @Override - public Object visitString(String s, Void p) { - return s; - } - - @Override - public Object visitType(TypeMirror t, Void p) { - return t; - } - - @Override - public Object visitEnumConstant(VariableElement c, Void p) { - return c; - } - - @Override - public Object visitAnnotation(AnnotationMirror a, Void p) { - return a; - } - - @Override - public Object visitArray(List vals, Void p) { - return vals; - } - - } - - public static boolean getAnnotationValueBoolean(AnnotationMirror mirror, String name) { - return (Boolean) getAnnotationValue(mirror, name).getValue(); - } - - public static String printException(Throwable e) { - StringWriter string = new StringWriter(); - PrintWriter writer = new PrintWriter(string); - e.printStackTrace(writer); - writer.flush(); - return e.getMessage() + "\r\n" + string.toString(); - } - - public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, Element element, Class annotationClass) { - return findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), annotationClass); - } - - public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List mirrors, Class annotationClass) { - TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName()); - for (AnnotationMirror mirror : mirrors) { - DeclaredType annotationType = mirror.getAnnotationType(); - TypeElement actualAnnotationType = (TypeElement) annotationType.asElement(); - if (actualAnnotationType.equals(expectedAnnotationType)) { - return mirror; - } - } - return null; - } - - private static PackageElement findPackageElement(Element type) { - List hierarchy = getElementHierarchy(type); - for (Element element : hierarchy) { - if (element.getKind() == ElementKind.PACKAGE) { - return (PackageElement) element; - } - } - return null; - } - - public static String firstLetterUpperCase(String name) { - if (name == null || name.isEmpty()) { - return name; - } - return Character.toUpperCase(name.charAt(0)) + name.substring(1, name.length()); - } - - public static String firstLetterLowerCase(String name) { - if (name == null || name.isEmpty()) { - return name; - } - return Character.toLowerCase(name.charAt(0)) + name.substring(1, name.length()); - } - - private static ExecutableElement getDeclaredMethod(TypeElement element, String name, TypeMirror[] params) { - List methods = ElementFilter.methodsIn(element.getEnclosedElements()); - method: for (ExecutableElement method : methods) { - if (!method.getSimpleName().toString().equals(name)) { - continue; - } - if (method.getParameters().size() != params.length) { - continue; - } - for (int i = 0; i < params.length; i++) { - TypeMirror param1 = params[i]; - TypeMirror param2 = method.getParameters().get(i).asType(); - if (param1.getKind() != TypeKind.TYPEVAR && param2.getKind() != TypeKind.TYPEVAR) { - if (!getQualifiedName(param1).equals(getQualifiedName(param2))) { - continue method; - } - } - } - return method; - } - return null; - } - - private static boolean isDeclaredMethod(TypeElement element, String name, TypeMirror[] params) { - return getDeclaredMethod(element, name, params) != null; - } - - public static boolean isDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) { - List superElements = getSuperTypes(element); - - for (TypeElement typeElement : superElements) { - if (isDeclaredMethod(typeElement, name, params)) { - return true; - } - } - return false; - } - - private static ExecutableElement getDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) { - List superElements = getSuperTypes(element); - - for (TypeElement typeElement : superElements) { - ExecutableElement declared = getDeclaredMethod(typeElement, name, params); - if (declared != null) { - return declared; - } - } - return null; - } - - public static ExecutableElement getDeclaredMethodRecursive(TypeElement element, String name, TypeMirror[] params) { - ExecutableElement declared = getDeclaredMethod(element, name, params); - if (declared != null) { - return declared; - } - return getDeclaredMethodInSuperType(element, name, params); - } - - public static boolean typeEquals(TypeMirror type1, TypeMirror type2) { - if (type1 == null && type2 == null) { - return true; - } else if (type1 == null || type2 == null) { - return false; - } - String qualified1 = getQualifiedName(type1); - String qualified2 = getQualifiedName(type2); - - if (type1.getKind() == TypeKind.ARRAY || type2.getKind() == TypeKind.ARRAY) { - if (type1.getKind() == TypeKind.ARRAY && type2.getKind() == TypeKind.ARRAY) { - return typeEquals(((ArrayType) type1).getComponentType(), ((ArrayType) type2).getComponentType()); - } else { - return false; - } - } - return qualified1.equals(qualified2); - } - - public static int compareByTypeHierarchy(TypeMirror t1, TypeMirror t2) { - if (typeEquals(t1, t2)) { - return 0; - } - Set t1SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t1))); - if (t1SuperSet.contains(getQualifiedName(t2))) { - return -1; - } - - Set t2SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t2))); - if (t2SuperSet.contains(getQualifiedName(t1))) { - return 1; - } - return 0; - } - - public static boolean canThrowType(List thrownTypes, TypeMirror exceptionType) { - if (Utils.containsType(thrownTypes, exceptionType)) { - return true; - } - - if (isRuntimeException(exceptionType)) { - return true; - } - - // search for any super types - TypeElement exceptionTypeElement = fromTypeMirror(exceptionType); - List superTypes = getSuperTypes(exceptionTypeElement); - for (TypeElement typeElement : superTypes) { - if (Utils.containsType(thrownTypes, typeElement.asType())) { - return true; - } - } - - return false; - } - - public static Modifier getVisibility(Set modifier) { - for (Modifier mod : modifier) { - if (mod == Modifier.PUBLIC || mod == Modifier.PRIVATE || mod == Modifier.PROTECTED) { - return mod; - } - } - return null; - } - - private static boolean isRuntimeException(TypeMirror type) { - Set typeSuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(type))); - String typeName = getQualifiedName(type); - if (!typeSuperSet.contains(Throwable.class.getCanonicalName()) && !typeName.equals(Throwable.class.getCanonicalName())) { - throw new IllegalArgumentException("Given type does not extend Throwable."); - } - return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || typeName.equals(RuntimeException.class.getCanonicalName()); - } - - private static boolean containsType(Collection collection, TypeMirror type) { - for (TypeMirror otherTypeMirror : collection) { - if (typeEquals(otherTypeMirror, type)) { - return true; - } - } - return false; - } - - public static boolean isTopLevelClass(TypeMirror importType) { - TypeElement type = fromTypeMirror(importType); - if (type != null && type.getEnclosingElement() != null) { - return !type.getEnclosingElement().getKind().isClass(); - } - return true; - } - - public static boolean isObject(TypeMirror actualType) { - return getQualifiedName(actualType).equals("java.lang.Object"); - } - - public static boolean isFieldAccessible(Element element, VariableElement variable) { - TypeElement type = Utils.findNearestEnclosingType(element); - TypeElement varType = Utils.findNearestEnclosingType(variable); - - while (type != null) { - if (typeEquals(type.asType(), varType.asType())) { - return true; - } - if (type.getSuperclass() != null) { - type = Utils.fromTypeMirror(type.getSuperclass()); - } else { - type = null; - } - } - return false; - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/ExtensionContext.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/ExtensionContext.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +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.codegen.processor.api; - -import javax.annotation.processing.*; - -import com.oracle.truffle.codegen.processor.api.element.*; - -public interface ExtensionContext { - - ProcessingEnvironment getProcessingEnvironment(); - - RoundEnvironment getRoundEnvironment(); - - WritableElementFactory getElementFactory(); - - void addGeneratedElement(WritableElement element); - - void removeGeneratedElement(WritableElement element); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/ExtensionProcessor.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/ExtensionProcessor.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +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.codegen.processor.api; - -import javax.lang.model.element.*; - -public interface ExtensionProcessor { - - void process(ExtensionContext context, AnnotationMirror mirror, Element element); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableAnnotationMirror.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableAnnotationMirror.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +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.codegen.processor.api.element; - -import javax.lang.model.element.*; - -public interface WritableAnnotationMirror extends AnnotationMirror { - - void setElementValue(ExecutableElement valueName, AnnotationValue value); - - AnnotationValue getElementValue(ExecutableElement valueName); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableElement.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +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.codegen.processor.api.element; - -import javax.lang.model.element.*; - -public interface WritableElement extends Element { - - void addAnnotationMirror(AnnotationMirror annotationMirror); - - void removeAnnotationMirror(AnnotationMirror annotationMirror); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableElementFactory.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableElementFactory.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +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.codegen.processor.api.element; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -public interface WritableElementFactory { - - WritableExecutableElement cloneExecutableElement(ExecutableElement method); - - WritableVariableElement cloneVariableElement(VariableElement parameter); - - WritableAnnotationMirror cloneAnnotationMirror(AnnotationMirror mirror); - - WritableVariableElement createParameter(TypeMirror type, String simpleName); - - WritableExecutableElement createExecutableElement(TypeMirror returnType, String methodName); - - WritableAnnotationMirror createAnnotationMirror(DeclaredType annotationClass); - - Name createName(String name); - - AnnotationValue createAnnotationValue(Object value); - - TypeMirror createTypeMirror(Class javaClass); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableExecutableElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableExecutableElement.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +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.codegen.processor.api.element; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -public interface WritableExecutableElement extends ExecutableElement, WritableElement { - - void setReturnType(TypeMirror type); - - void setDefaultValue(AnnotationValue defaultValue); - - void addParameter(VariableElement parameter); - - void removeParameter(VariableElement parameter); - - void addThrownType(TypeMirror thrownType); - - void removeThrownType(TypeMirror thrownType); - - void setSimpleName(Name name); - - void setVarArgs(boolean varargs); - - void setBody(String body); - - String getBody(); -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableVariableElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableVariableElement.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +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.codegen.processor.api.element; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -public interface WritableVariableElement extends VariableElement, WritableElement { - - void setSimpleName(Name name); - - void setType(TypeMirror type); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationMirror.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationMirror.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +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.codegen.processor.ast; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.api.element.*; - -public class CodeAnnotationMirror implements WritableAnnotationMirror { - - private final DeclaredType annotationType; - private final Map values = new LinkedHashMap<>(); - - public CodeAnnotationMirror(DeclaredType annotationType) { - this.annotationType = annotationType; - } - - @Override - public DeclaredType getAnnotationType() { - return annotationType; - } - - @Override - public Map getElementValues() { - return values; - } - - @Override - public AnnotationValue getElementValue(ExecutableElement method) { - return values.get(method); - } - - @Override - public void setElementValue(ExecutableElement method, AnnotationValue value) { - values.put(method, value); - } - - public ExecutableElement findExecutableElement(String name) { - return Utils.findExecutableElement(annotationType, name); - } - - public static CodeAnnotationMirror clone(AnnotationMirror mirror) { - CodeAnnotationMirror copy = new CodeAnnotationMirror(mirror.getAnnotationType()); - for (ExecutableElement key : mirror.getElementValues().keySet()) { - copy.setElementValue(key, mirror.getElementValues().get(key)); - } - return copy; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationValue.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationValue.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +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.codegen.processor.ast; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -public class CodeAnnotationValue implements AnnotationValue { - - private final Object value; - - public CodeAnnotationValue(Object value) { - Objects.requireNonNull(value); - if ((value instanceof AnnotationMirror) || (value instanceof List) || (value instanceof Boolean) || (value instanceof Byte) || (value instanceof Character) || (value instanceof Double) || - (value instanceof VariableElement) || (value instanceof Float) || (value instanceof Integer) || (value instanceof Long) || (value instanceof Short) || - (value instanceof String) || (value instanceof TypeMirror)) { - this.value = value; - } else { - throw new IllegalArgumentException("Invalid annotation value type " + value.getClass().getName()); - } - } - - @Override - public Object getValue() { - return value; - } - - @SuppressWarnings("unchecked") - @Override - public R accept(AnnotationValueVisitor v, P p) { - if (value instanceof AnnotationMirror) { - return v.visitAnnotation((AnnotationMirror) value, p); - } else if (value instanceof List) { - return v.visitArray((List) value, p); - } else if (value instanceof Boolean) { - return v.visitBoolean((boolean) value, p); - } else if (value instanceof Byte) { - return v.visitByte((byte) value, p); - } else if (value instanceof Character) { - return v.visitChar((char) value, p); - } else if (value instanceof Double) { - return v.visitDouble((double) value, p); - } else if (value instanceof VariableElement) { - return v.visitEnumConstant((VariableElement) value, p); - } else if (value instanceof Float) { - return v.visitFloat((float) value, p); - } else if (value instanceof Integer) { - return v.visitInt((int) value, p); - } else if (value instanceof Long) { - return v.visitLong((long) value, p); - } else if (value instanceof Short) { - return v.visitShort((short) value, p); - } else if (value instanceof String) { - return v.visitString((String) value, p); - } else if (value instanceof TypeMirror) { - return v.visitType((TypeMirror) value, p); - } else { - return v.visitUnknown(this, p); - } - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeCompilationUnit.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeCompilationUnit.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +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.codegen.processor.ast; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -public class CodeCompilationUnit extends CodeElement { - - public CodeCompilationUnit() { - super(Collections. emptySet()); - } - - @Override - public TypeMirror asType() { - throw new UnsupportedOperationException(); - } - - @Override - public ElementKind getKind() { - return ElementKind.OTHER; - } - - @Override - public Name getSimpleName() { - throw new UnsupportedOperationException(); - } - - @Override - public R accept(ElementVisitor v, P p) { - for (Element type : getEnclosedElements()) { - if (type.getKind().isClass()) { - type.accept(v, p); - } else { - throw new ClassCastException(type.getClass().getName()); - } - } - return null; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,360 +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.codegen.processor.ast; - -import java.io.*; -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; - -import com.oracle.truffle.codegen.processor.api.element.*; -import com.oracle.truffle.codegen.processor.codewriter.*; - -public abstract class CodeElement implements WritableElement, GeneratedElement { - - private final Set modifiers; - private List annotations; - private List enclosedElements; - - private Element enclosingElement; - - private Element generatorElement; - private AnnotationMirror generatorAnnotationMirror; - - public CodeElement() { - this.modifiers = new LinkedHashSet<>(); - } - - @Override - public void setGeneratorAnnotationMirror(AnnotationMirror mirror) { - this.generatorAnnotationMirror = mirror; - } - - @Override - public void setGeneratorElement(Element element) { - this.generatorElement = element; - } - - @Override - public AnnotationMirror getGeneratorAnnotationMirror() { - return generatorAnnotationMirror; - } - - @Override - public Element getGeneratorElement() { - return generatorElement; - } - - public CodeElement(Set modifiers) { - this.modifiers = new LinkedHashSet<>(modifiers); - } - - public E add(E element) { - if (element == null) { - throw new NullPointerException(); - } - getEnclosedElements().add(element); - return element; - } - - public void remove(E element) { - getEnclosedElements().remove(element); - } - - @Override - public Set getModifiers() { - return modifiers; - } - - @Override - public List getEnclosedElements() { - if (enclosedElements == null) { - enclosedElements = parentableList(this, new ArrayList()); - } - return enclosedElements; - } - - @Override - public List getAnnotationMirrors() { - if (annotations == null) { - annotations = parentableList(this, new ArrayList()); - } - return annotations; - } - - /** - * Support JDK8 langtools. - * - * @param annotationType - */ - public A[] getAnnotationsByType(Class annotationType) { - throw new UnsupportedOperationException(); - } - - /** - * Support for some JDK8 builds. (remove after jdk8 is released) - * - * @param annotationType - */ - public A[] getAnnotations(Class annotationType) { - throw new UnsupportedOperationException(); - } - - /** - * Support for some JDK8 builds. (remove after jdk8 is released) - * - * @param annotationType - */ - public A getAnnotation(Class annotationType) { - throw new UnsupportedOperationException(); - } - - @Override - public void addAnnotationMirror(AnnotationMirror annotationMirror) { - getAnnotationMirrors().add(annotationMirror); - } - - public void removeAnnotationMirror(AnnotationMirror annotationMirror) { - getAnnotationMirrors().remove(annotationMirror); - } - - void setEnclosingElement(Element parent) { - this.enclosingElement = parent; - } - - public Element getEnclosingElement() { - return enclosingElement; - } - - public CodeTypeElement getEnclosingClass() { - Element p = enclosingElement; - while (p != null && p.getKind() != ElementKind.CLASS && p.getKind() != ElementKind.ENUM) { - p = p.getEnclosingElement(); - } - return (CodeTypeElement) p; - } - - List parentableList(Element parent, List list) { - return new ParentableList<>(parent, list); - } - - @Override - public String toString() { - StringBuilderCodeWriter codeWriter = new StringBuilderCodeWriter(); - accept(codeWriter, null); - return codeWriter.getString(); - } - - private static class StringBuilderCodeWriter extends AbstractCodeWriter { - - public StringBuilderCodeWriter() { - this.writer = new CharArrayWriter(); - } - - @Override - protected Writer createWriter(CodeTypeElement clazz) throws IOException { - return writer; - } - - public String getString() { - return new String(((CharArrayWriter) writer).toCharArray()).trim(); - } - - } - - private static class ParentableList implements List { - - private final Element parent; - private final List delegate; - - public ParentableList(Element parent, List delegate) { - this.parent = parent; - this.delegate = delegate; - } - - private void addImpl(T element) { - if (element != null) { - if (element instanceof CodeElement) { - ((CodeElement) element).setEnclosingElement(parent); - } - } - } - - private static void removeImpl(Object element) { - if (element instanceof CodeElement) { - ((CodeElement) element).setEnclosingElement(null); - } - } - - @Override - public int size() { - return delegate.size(); - } - - @Override - public boolean isEmpty() { - return delegate.isEmpty(); - } - - @Override - public boolean contains(Object o) { - return delegate.contains(o); - } - - @Override - public Iterator iterator() { - return delegate.iterator(); - } - - @Override - public Object[] toArray() { - return delegate.toArray(); - } - - @Override - public E[] toArray(E[] a) { - return delegate.toArray(a); - } - - @Override - public boolean add(T e) { - addImpl(e); - return delegate.add(e); - } - - @Override - public boolean remove(Object o) { - boolean removed = delegate.remove(o); - if (removed) { - removeImpl(o); - } - return removed; - } - - @Override - public boolean containsAll(Collection c) { - return delegate.containsAll(c); - } - - @Override - public boolean addAll(Collection c) { - if (c != null) { - for (T t : c) { - addImpl(t); - } - } - return delegate.addAll(c); - } - - @Override - public boolean addAll(int index, Collection c) { - if (c != null) { - for (T t : c) { - addImpl(t); - } - } - return delegate.addAll(index, c); - } - - @Override - public boolean removeAll(Collection c) { - if (c != null) { - for (Object t : c) { - removeImpl(t); - } - } - return delegate.removeAll(c); - } - - @Override - public String toString() { - return delegate.toString(); - } - - @Override - public boolean retainAll(Collection c) { - throw new UnsupportedOperationException("Not supported by parentable list"); - } - - @Override - public void clear() { - for (Object e : this) { - removeImpl(e); - } - delegate.clear(); - } - - @Override - public T get(int index) { - return delegate.get(index); - } - - @Override - public T set(int index, T element) { - removeImpl(delegate.get(index)); - addImpl(element); - return delegate.set(index, element); - } - - @Override - public void add(int index, T element) { - addImpl(element); - delegate.add(index, element); - } - - @Override - public T remove(int index) { - T element = delegate.remove(index); - removeImpl(element); - return element; - } - - @Override - public int indexOf(Object o) { - return delegate.indexOf(o); - } - - @Override - public int lastIndexOf(Object o) { - return delegate.lastIndexOf(o); - } - - @Override - public ListIterator listIterator() { - return delegate.listIterator(); - } - - @Override - public ListIterator listIterator(int index) { - return delegate.listIterator(index); - } - - @Override - public List subList(int fromIndex, int toIndex) { - return new ParentableList<>(parent, delegate.subList(fromIndex, toIndex)); - } - - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElementScanner.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElementScanner.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +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.codegen.processor.ast; - -import javax.lang.model.element.*; -import javax.lang.model.util.*; - -public abstract class CodeElementScanner extends ElementScanner7 { - - @Override - public final R visitExecutable(ExecutableElement e, P p) { - return visitExecutable(cast(e, CodeExecutableElement.class), p); - } - - public R visitExecutable(CodeExecutableElement e, P p) { - R ret = super.visitExecutable(e, p); - if (e.getBodyTree() != null) { - visitTree(e.getBodyTree(), p); - } - return ret; - } - - @Override - public R visitPackage(PackageElement e, P p) { - return super.visitPackage(e, p); - } - - @Override - public final R visitType(TypeElement e, P p) { - return visitType(cast(e, CodeTypeElement.class), p); - } - - public R visitType(CodeTypeElement e, P p) { - return super.visitType(e, p); - } - - @Override - public R visitTypeParameter(TypeParameterElement e, P p) { - return super.visitTypeParameter(e, p); - } - - private static E cast(Element element, Class clazz) { - return clazz.cast(element); - } - - public void visitTree(CodeTree e, P p) { - for (CodeTree tree : e.getEnclosedElements()) { - tree.acceptCodeElementScanner(this, p); - } - } - - @SuppressWarnings("unused") - public void visitImport(CodeImport e, P p) { - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,231 +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.codegen.processor.ast; - -import java.util.*; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.api.element.*; - -public class CodeExecutableElement extends CodeElement implements WritableExecutableElement { - - private final List throwables = new ArrayList<>(); - private final List parameters = parentableList(this, new ArrayList()); - - private TypeMirror returnType; - private Name name; - - private CodeTree bodyTree; - private String body; - private AnnotationValue defaultValue; - private boolean varArgs; - - public CodeExecutableElement(TypeMirror returnType, String name) { - super(Utils.modifiers()); - this.returnType = returnType; - this.name = CodeNames.of(name); - } - - public CodeExecutableElement(Set modifiers, TypeMirror returnType, String name, CodeVariableElement... parameters) { - super(modifiers); - this.returnType = returnType; - this.name = CodeNames.of(name); - for (CodeVariableElement codeParameter : parameters) { - addParameter(codeParameter); - } - } - - /* Support JDK8 langtools. */ - public boolean isDefault() { - return false; - } - - @Override - public List getThrownTypes() { - return throwables; - } - - @Override - public TypeMirror asType() { - return returnType; - } - - @Override - public ElementKind getKind() { - if (getReturnType() == null) { - return ElementKind.CONSTRUCTOR; - } else { - return ElementKind.METHOD; - } - } - - @Override - public List getTypeParameters() { - return Collections.emptyList(); - } - - @Override - public void setVarArgs(boolean varargs) { - this.varArgs = varargs; - } - - @Override - public boolean isVarArgs() { - return varArgs; - } - - @Override - public void setDefaultValue(AnnotationValue defaultValue) { - this.defaultValue = defaultValue; - } - - @Override - public AnnotationValue getDefaultValue() { - return defaultValue; - } - - @Override - public Name getSimpleName() { - return name; - } - - public CodeTreeBuilder createBuilder() { - CodeTreeBuilder builder = new CodeTreeBuilder(null); - this.bodyTree = builder.getTree(); - this.bodyTree.setEnclosingElement(this); - this.body = null; - return builder; - } - - public void setBodyTree(CodeTree body) { - this.bodyTree = body; - } - - public CodeTree getBodyTree() { - return bodyTree; - } - - public TypeMirror getReturnType() { - return returnType; - } - - @Override - public List getParameters() { - return parameters; - } - - public TypeMirror[] getParameterTypes() { - TypeMirror[] types = new TypeMirror[getParameters().size()]; - for (int i = 0; i < types.length; i++) { - types[i] = parameters.get(i).asType(); - } - return types; - } - - @Override - public void setReturnType(TypeMirror type) { - returnType = type; - } - - @Override - public void addParameter(VariableElement parameter) { - parameters.add(parameter); - } - - @Override - public void removeParameter(VariableElement parameter) { - parameters.remove(parameter); - } - - public void removeParameter(String varName) { - VariableElement remove = null; - for (VariableElement var : getParameters()) { - if (var.getSimpleName().toString().equals(varName)) { - remove = var; - break; - } - } - if (remove != null) { - parameters.remove(remove); - } - } - - @Override - public void addThrownType(TypeMirror thrownType) { - throwables.add(thrownType); - } - - @Override - public void removeThrownType(TypeMirror thrownType) { - throwables.remove(thrownType); - } - - @Override - public void setSimpleName(Name name) { - this.name = name; - } - - @Override - public void setBody(String body) { - this.body = body; - } - - @Override - public String getBody() { - return body; - } - - @Override - public R accept(ElementVisitor v, P p) { - return v.visitExecutable(this, p); - } - - public static CodeExecutableElement clone(@SuppressWarnings("unused") ProcessingEnvironment env, ExecutableElement method) { - CodeExecutableElement copy = new CodeExecutableElement(method.getReturnType(), method.getSimpleName().toString()); - for (TypeMirror thrownType : method.getThrownTypes()) { - copy.addThrownType(thrownType); - } - copy.setDefaultValue(method.getDefaultValue()); - - for (AnnotationMirror mirror : method.getAnnotationMirrors()) { - copy.addAnnotationMirror(mirror); - } - for (VariableElement var : method.getParameters()) { - copy.addParameter(CodeVariableElement.clone(var)); - } - for (Element element : method.getEnclosedElements()) { - copy.add(element); - } - copy.getModifiers().addAll(method.getModifiers()); - copy.setVarArgs(method.isVarArgs()); - return copy; - } - - public TypeMirror getReceiverType() { - throw new UnsupportedOperationException(); - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeImport.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeImport.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +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.codegen.processor.ast; - -import javax.lang.model.type.*; - -public class CodeImport implements Comparable { - - private final TypeMirror importType; - private final String importString; - private final boolean staticImport; - - public CodeImport(TypeMirror importedType, String importString, boolean staticImport) { - this.importType = importedType; - this.importString = importString; - this.staticImport = staticImport; - } - - public TypeMirror getImportType() { - return importType; - } - - public boolean isStaticImport() { - return staticImport; - } - - public String getImportString() { - return importString; - } - - @Override - public int compareTo(CodeImport o) { - if (staticImport && !o.staticImport) { - return 1; - } else if (!staticImport && o.staticImport) { - return -1; - } else { - return importString.compareTo(o.getImportString()); - } - } - - public

void accept(CodeElementScanner s, P p) { - s.visitImport(this, p); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((importString == null) ? 0 : importString.hashCode()); - result = prime * result + (staticImport ? 1231 : 1237); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - CodeImport other = (CodeImport) obj; - if (importString == null) { - if (other.importString != null) { - return false; - } - } else if (!importString.equals(other.importString)) { - return false; - } - if (staticImport != other.staticImport) { - return false; - } - return true; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeNames.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeNames.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +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.codegen.processor.ast; - -import java.util.*; - -import javax.lang.model.element.*; - -public abstract class CodeNames { - - private static Map names = new HashMap<>(); - - public static Name of(String value) { - Name name = names.get(value); - if (name == null) { - name = new NameImpl(value); - names.put(value, name); - } - return name; - } - - private static class NameImpl implements Name { - - private final String name; - - public NameImpl(String name) { - this.name = name; - } - - @Override - public int length() { - return name.length(); - } - - @Override - public char charAt(int index) { - return name.charAt(index); - } - - @Override - public CharSequence subSequence(int start, int end) { - return name.subSequence(start, end); - } - - @Override - public boolean contentEquals(CharSequence cs) { - return name.contentEquals(cs); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Name) { - return ((Name) obj).contentEquals(name); - } - return super.equals(obj); - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - @Override - public String toString() { - return name; - } - - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTree.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTree.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +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.codegen.processor.ast; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -public class CodeTree extends CodeElement { - - private final CodeTreeKind kind; - - private final TypeMirror type; - private final String string; - - public CodeTree(CodeTreeKind kind, TypeMirror type, String string) { - this.kind = kind; - this.type = type; - this.string = string; - } - - public TypeMirror getType() { - return type; - } - - public CodeTreeKind getCodeKind() { - return kind; - } - - public String getString() { - return string; - } - - public

void acceptCodeElementScanner(CodeElementScanner s, P p) { - s.visitTree(this, p); - } - - @Override - public TypeMirror asType() { - return type; - } - - @Override - public ElementKind getKind() { - return ElementKind.OTHER; - } - - @Override - public Name getSimpleName() { - return CodeNames.of(getString()); - } - - @Override - public R accept(ElementVisitor v, P p) { - if (v instanceof CodeElementScanner) { - acceptCodeElementScanner((CodeElementScanner) v, p); - return null; - } else { - throw new UnsupportedOperationException(); - } - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,818 +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.codegen.processor.ast; - -import static com.oracle.truffle.codegen.processor.ast.CodeTreeKind.*; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; - -public class CodeTreeBuilder { - - private final CodeTreeBuilder parent; - - private BuilderCodeTree currentElement; - private final BuilderCodeTree root; - - private int treeCount; - - public CodeTreeBuilder(CodeTreeBuilder parent) { - this.root = new BuilderCodeTree(GROUP, null, null); - this.currentElement = root; - this.parent = parent; - } - - @Override - public String toString() { - return root.toString(); - } - - public int getTreeCount() { - return treeCount; - } - - public boolean isEmpty() { - return treeCount == 0; - } - - public CodeTreeBuilder statement(String statement) { - return startStatement().string(statement).end(); - } - - public CodeTreeBuilder statement(CodeTree statement) { - return startStatement().tree(statement).end(); - } - - public static CodeTreeBuilder createBuilder() { - return new CodeTreeBuilder(null); - } - - public static CodeTree singleString(String s) { - return new CodeTreeBuilder(null).string(s).getTree(); - } - - public static CodeTree singleType(TypeMirror s) { - return new CodeTreeBuilder(null).type(s).getTree(); - } - - private CodeTreeBuilder push(CodeTreeKind kind) { - return push(new BuilderCodeTree(kind, null, null)); - } - - private CodeTreeBuilder push(String string) { - return push(new BuilderCodeTree(CodeTreeKind.STRING, null, string)); - } - - private CodeTreeBuilder push(TypeMirror type) { - return push(new BuilderCodeTree(CodeTreeKind.TYPE, type, null)); - } - - private CodeTreeBuilder push(CodeTreeKind kind, TypeMirror type, String string) { - return push(new BuilderCodeTree(kind, type, string)); - } - - private CodeTreeBuilder push(BuilderCodeTree tree) { - if (currentElement != null) { - currentElement.add(tree); - } - switch (tree.getCodeKind()) { - case COMMA_GROUP: - case GROUP: - case INDENT: - currentElement = tree; - break; - } - treeCount++; - return this; - } - - private void clearLast(CodeTreeKind kind) { - if (clearLastRec(kind, currentElement.getEnclosedElements())) { - treeCount--; - } - } - - public CodeTreeBuilder startStatement() { - startGroup(); - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - string(";").newLine(); - } - - @Override - public void afterEnd() { - } - }); - return this; - } - - public CodeTreeBuilder startGroup() { - return push(CodeTreeKind.GROUP); - } - - public CodeTreeBuilder startCommaGroup() { - return push(CodeTreeKind.COMMA_GROUP); - } - - public CodeTreeBuilder startCall(String callSite) { - return startCall(null, callSite); - } - - public CodeTreeBuilder startCall(String receiver, String callSite) { - if (receiver == null) { - return startGroup().string(callSite).startParanthesesCommaGroup().endAfter(); - } else { - return startGroup().string(receiver).string(".").string(callSite).startParanthesesCommaGroup().endAfter(); - } - } - - public CodeTreeBuilder startStaticCall(TypeMirror type, String methodName) { - return startGroup().push(CodeTreeKind.STATIC_METHOD_REFERENCE, type, methodName).startParanthesesCommaGroup().endAfter(); - } - - public CodeTreeBuilder startStaticCall(ExecutableElement method) { - return startStaticCall(Utils.findNearestEnclosingType(method).asType(), method.getSimpleName().toString()); - } - - public CodeTreeBuilder staticReference(TypeMirror type, String fieldName) { - return push(CodeTreeKind.STATIC_FIELD_REFERENCE, type, fieldName); - } - - private CodeTreeBuilder endAndWhitespaceAfter() { - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - } - - @Override - public void afterEnd() { - string(" "); - end(); - } - }); - return this; - } - - private CodeTreeBuilder endAfter() { - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - } - - @Override - public void afterEnd() { - end(); - } - }); - return this; - } - - private CodeTreeBuilder startParanthesesCommaGroup() { - startGroup(); - string("(").startCommaGroup(); - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - } - - @Override - public void afterEnd() { - string(")"); - } - }); - endAfter(); - return this; - } - - private CodeTreeBuilder startCurlyBracesCommaGroup() { - startGroup(); - string("{").startCommaGroup(); - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - } - - @Override - public void afterEnd() { - string("}"); - } - }); - endAfter(); - return this; - } - - public CodeTreeBuilder startParantheses() { - startGroup(); - string("(").startGroup(); - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - } - - @Override - public void afterEnd() { - string(")"); - } - }); - endAfter(); - return this; - } - - public CodeTreeBuilder doubleQuote(String s) { - return startGroup().string("\"" + s + "\"").end(); - } - - public CodeTreeBuilder string(String chunk1) { - return push(chunk1); - } - - public CodeTreeBuilder string(String chunk1, String chunk2) { - return push(GROUP).string(chunk1).string(chunk2).end(); - } - - public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3) { - return push(GROUP).string(chunk1).string(chunk2).string(chunk3).end(); - } - - public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4) { - return push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4).end(); - } - - public CodeTreeBuilder tree(CodeTree treeToAdd) { - if (treeToAdd instanceof BuilderCodeTree) { - return push((BuilderCodeTree) treeToAdd).end(); - } else { - BuilderCodeTree tree = new BuilderCodeTree(GROUP, null, null); - tree.add(treeToAdd); - return push(tree).end(); - } - } - - public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4, String... chunks) { - push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4); - for (int i = 0; i < chunks.length; i++) { - string(chunks[i]); - } - return end(); - } - - public CodeTreeBuilder dot() { - return string("."); - } - - public CodeTreeBuilder newLine() { - return push(NEW_LINE); - } - - public CodeTreeBuilder startWhile() { - return startGroup().string("while ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); - } - - public CodeTreeBuilder startIf() { - return startGroup().string("if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); - } - - public boolean startIf(boolean elseIf) { - if (elseIf) { - startElseIf(); - } else { - startIf(); - } - return true; - } - - public CodeTreeBuilder startElseIf() { - clearLast(CodeTreeKind.NEW_LINE); - return startGroup().string(" else if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); - } - - public CodeTreeBuilder startElseBlock() { - clearLast(CodeTreeKind.NEW_LINE); - return startGroup().string(" else ").startBlock().endAfter(); - } - - private boolean clearLastRec(CodeTreeKind kind, List children) { - for (int i = children.size() - 1; i >= 0; i--) { - CodeTree child = children.get(i); - if (child.getCodeKind() == kind) { - children.remove(children.get(i)); - return true; - } else { - if (clearLastRec(kind, child.getEnclosedElements())) { - return true; - } - } - } - return false; - } - - public CodeTreeBuilder startCase() { - startGroup().string("case "); - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - string(" :").newLine(); - } - - @Override - public void afterEnd() { - } - }); - return this; - } - - public CodeTreeBuilder caseDefault() { - return startGroup().string("default :").newLine().end(); - } - - public CodeTreeBuilder startSwitch() { - return startGroup().string("switch ").startParanthesesCommaGroup().endAndWhitespaceAfter(); - } - - public CodeTreeBuilder startReturn() { - ExecutableElement method = findMethod(); - if (method != null && Utils.isVoid(method.getReturnType())) { - startGroup(); - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - string(";").newLine(); // complete statement to execute - } - - @Override - public void afterEnd() { - string("return").string(";").newLine(); // emit a return; - } - }); - return this; - } else { - return startStatement().string("return "); - } - } - - public CodeTreeBuilder startAssert() { - return startStatement().string("assert "); - } - - public CodeTreeBuilder startNewArray(ArrayType arrayType, CodeTree size) { - startGroup().string("new ").type(arrayType.getComponentType()).string("["); - if (size != null) { - tree(size); - } - string("]"); - if (size == null) { - string(" "); - startCurlyBracesCommaGroup().endAfter(); - } - return this; - } - - public CodeTreeBuilder startNew(TypeMirror uninializedNodeClass) { - return startGroup().string("new ").type(uninializedNodeClass).startParanthesesCommaGroup().endAfter(); - } - - public CodeTreeBuilder startNew(String typeName) { - return startGroup().string("new ").string(typeName).startParanthesesCommaGroup().endAfter(); - } - - public CodeTreeBuilder startIndention() { - return push(CodeTreeKind.INDENT); - } - - public CodeTreeBuilder end(int times) { - for (int i = 0; i < times; i++) { - end(); - } - return this; - } - - public CodeTreeBuilder end() { - BuilderCodeTree tree = currentElement; - EndCallback callback = tree.getAtEndListener(); - if (callback != null) { - callback.beforeEnd(); - toParent(); - callback.afterEnd(); - } else { - toParent(); - } - return this; - } - - private void toParent() { - Element parentElement = currentElement.getEnclosingElement(); - if (currentElement != root) { - this.currentElement = (BuilderCodeTree) parentElement; - } else { - this.currentElement = root; - } - } - - public CodeTreeBuilder startBlock() { - startGroup(); - string("{").newLine().startIndention(); - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - } - - @Override - public void afterEnd() { - string("}").newLine(); - } - }); - endAfter(); - return this; - } - - private void registerCallBack(EndCallback callback) { - currentElement.registerAtEnd(callback); - } - - public CodeTreeBuilder defaultDeclaration(TypeMirror type, String name) { - if (!Utils.isVoid(type)) { - startStatement(); - type(type); - string(" "); - string(name); - string(" = "); - defaultValue(type); - end(); // statement - } - return this; - } - - public CodeTreeBuilder declaration(TypeMirror type, String name, String init) { - return declaration(type, name, singleString(init)); - } - - public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTree init) { - if (Utils.isVoid(type)) { - startStatement(); - tree(init); - end(); - } else { - startStatement(); - type(type); - string(" "); - string(name); - if (init != null) { - string(" = "); - tree(init); - } - end(); // statement - } - return this; - } - - public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTreeBuilder init) { - if (init == this) { - throw new IllegalArgumentException("Recursive builder usage."); - } - return declaration(type, name, init.getTree()); - } - - public CodeTreeBuilder declaration(TypeMirror type, String name) { - return declaration(type, name, (CodeTree) null); - } - - public CodeTreeBuilder create() { - return new CodeTreeBuilder(this); - } - - public CodeTreeBuilder type(TypeMirror type) { - return push(type); - } - - public CodeTreeBuilder typeLiteral(TypeMirror type) { - return startGroup().type(type).string(".class").end(); - } - - private void assertRoot() { - if (currentElement != root) { - throw new IllegalStateException("CodeTreeBuilder was not ended properly."); - } - } - - public CodeTreeBuilder startCaseBlock() { - return startIndention(); - } - - public CodeTreeBuilder startThrow() { - return startStatement().string("throw "); - } - - public CodeTree getTree() { - assertRoot(); - return root; - } - - public CodeTree getRoot() { - return root; - } - - public CodeTreeBuilder cast(String baseClassName) { - string("(").string(baseClassName).string(") "); - return this; - } - - public CodeTreeBuilder cast(TypeMirror type, CodeTree content) { - if (Utils.isVoid(type)) { - tree(content); - return this; - } else if (type.getKind() == TypeKind.DECLARED && Utils.getQualifiedName(type).equals("java.lang.Object")) { - tree(content); - return this; - } else { - return startGroup().string("(").type(type).string(")").string(" ").tree(content).end(); - } - } - - public CodeTreeBuilder startSuperCall() { - return string("super").startParanthesesCommaGroup(); - } - - public CodeTreeBuilder returnFalse() { - return startReturn().string("false").end(); - } - - public CodeTreeBuilder returnStatement() { - return statement("return"); - } - - public ExecutableElement findMethod() { - Element element = currentElement; - while (element != null && (element.getKind() != ElementKind.METHOD && (element.getKind() != ElementKind.CONSTRUCTOR))) { - element = element.getEnclosingElement(); - } - ExecutableElement found = element != null ? (ExecutableElement) element : null; - if (found == null && parent != null) { - found = parent.findMethod(); - } - return found; - } - - public CodeTreeBuilder returnTrue() { - return startReturn().string("true").end(); - } - - public CodeTreeBuilder instanceOf(CodeTree var, CodeTree type) { - tree(var).string(" instanceof ").tree(type); - return this; - } - - public CodeTreeBuilder instanceOf(String var, String type) { - return instanceOf(singleString(var), singleString(type)); - } - - public CodeTreeBuilder instanceOf(String var, TypeMirror type) { - TypeElement element = Utils.fromTypeMirror(type); - if (element == null) { - throw new IllegalArgumentException("Cannot call instanceof for a non supported type: " + type.getKind()); - } - return instanceOf(singleString(var), singleType(type)); - } - - public CodeTreeBuilder defaultValue(TypeMirror mirror) { - switch (mirror.getKind()) { - case VOID: - return string(""); - case ARRAY: - case DECLARED: - case PACKAGE: - case NULL: - return string("null"); - case BOOLEAN: - return string("false"); - case BYTE: - return string("(byte) 0"); - case CHAR: - return string("(char) 0"); - case DOUBLE: - return string("0.0D"); - case LONG: - return string("0L"); - case INT: - return string("0"); - case FLOAT: - return string("0.0F"); - case SHORT: - return string("(short) 0"); - default: - throw new AssertionError(); - } - } - - public CodeTreeBuilder assertFalse() { - return startAssert().string("false").end(); - } - - public CodeTreeBuilder breakStatement() { - return statement("break"); - } - - public CodeTreeBuilder isNull() { - return string(" == null"); - } - - public CodeTreeBuilder isNotNull() { - return string(" != null"); - } - - public CodeTreeBuilder is(CodeTree tree) { - return string(" == ").tree(tree); - } - - public CodeTreeBuilder startTryBlock() { - return string("try ").startBlock(); - } - - public CodeTreeBuilder startCatchBlock(TypeMirror exceptionType, String localVarName) { - clearLast(CodeTreeKind.NEW_LINE); - string(" catch (").type(exceptionType).string(" ").string(localVarName).string(") "); - return startBlock(); - } - - public CodeTreeBuilder startFinallyBlock() { - clearLast(CodeTreeKind.NEW_LINE); - string(" finally "); - return startBlock(); - } - - public CodeTreeBuilder nullLiteral() { - return string("null"); - } - - private static class BuilderCodeTree extends CodeTree { - - private EndCallback atEndListener; - - public BuilderCodeTree(CodeTreeKind kind, TypeMirror type, String string) { - super(kind, type, string); - } - - public void registerAtEnd(EndCallback atEnd) { - if (this.atEndListener != null) { - this.atEndListener = new CompoundCallback(this.atEndListener, atEnd); - } else { - this.atEndListener = atEnd; - } - } - - public EndCallback getAtEndListener() { - return atEndListener; - } - - @Override - public String toString() { - final StringBuilder b = new StringBuilder(); - acceptCodeElementScanner(new Printer(b), null); - return b.toString(); - } - - private static class CompoundCallback implements EndCallback { - - private final EndCallback callback1; - private final EndCallback callback2; - - public CompoundCallback(EndCallback callback1, EndCallback callback2) { - this.callback1 = callback1; - this.callback2 = callback2; - } - - @Override - public void afterEnd() { - callback1.afterEnd(); - callback2.afterEnd(); - } - - @Override - public void beforeEnd() { - callback1.beforeEnd(); - callback1.beforeEnd(); - } - } - - } - - private interface EndCallback { - - void beforeEnd(); - - void afterEnd(); - } - - private static class Printer extends CodeElementScanner { - - private int indent; - private boolean newLine; - private final String ln = "\n"; - - private final StringBuilder b; - - Printer(StringBuilder b) { - this.b = b; - } - - @Override - public void visitTree(CodeTree e, Void p) { - switch (e.getCodeKind()) { - case COMMA_GROUP: - List children = e.getEnclosedElements(); - for (int i = 0; i < children.size(); i++) { - children.get(i).acceptCodeElementScanner(this, p); - if (i < e.getEnclosedElements().size() - 1) { - b.append(", "); - } - } - break; - case GROUP: - super.visitTree(e, p); - break; - case INDENT: - indent(); - super.visitTree(e, p); - dedent(); - break; - case NEW_LINE: - writeLn(); - break; - case STRING: - if (e.getString() != null) { - write(e.getString()); - } else { - write("null"); - } - break; - case TYPE: - write(Utils.getSimpleName(e.getType())); - break; - default: - assert false; - return; - } - } - - private void indent() { - indent++; - } - - private void dedent() { - indent--; - } - - private void writeLn() { - write(ln); - newLine = true; - } - - private void write(String m) { - if (newLine && m != ln) { - writeIndent(); - newLine = false; - } - b.append(m); - } - - private void writeIndent() { - for (int i = 0; i < indent; i++) { - b.append(" "); - } - } - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeKind.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeKind.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +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.codegen.processor.ast; - -public enum CodeTreeKind { - STATIC_FIELD_REFERENCE, STATIC_METHOD_REFERENCE, GROUP, COMMA_GROUP, INDENT, STRING, NEW_LINE, TYPE; -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeVariable.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeVariable.java Mon Jul 01 20:32:20 2013 +0200 +++ /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.codegen.processor.ast; - -public class CodeTreeVariable extends CodeTree { - - private final String name; - - private CodeTree value; - - public CodeTreeVariable() { - super(CodeTreeKind.GROUP, null, null); - this.name = ""; - } - - public CodeTreeVariable(String name) { - super(CodeTreeKind.GROUP, null, null); - this.name = name; - } - - public String getName() { - return name; - } - - public void set(CodeTree tree) { - if (value == tree) { - return; - } - if (this.value != null) { - remove(this.value); - } - this.value = tree; - add(tree); - } - - public CodeTree get() { - return value; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeElement.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +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.codegen.processor.ast; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.codegen.processor.ast.CodeTypeMirror.DeclaredCodeTypeMirror; - -public class CodeTypeElement extends CodeElement implements TypeElement { - - private final List imports = parentableList(this, new ArrayList()); - - private final PackageElement packageElement; - - private final Name simpleName; - private final Name packageName; - private Name qualifiedName; - - private final List implementsInterfaces = new ArrayList<>(); - private final ElementKind kind; - private TypeMirror superClass; - - private final DeclaredCodeTypeMirror mirror = new DeclaredCodeTypeMirror(this); - - public CodeTypeElement(Set modifiers, ElementKind kind, PackageElement packageElement, String simpleName) { - super(modifiers); - this.kind = kind; - this.packageElement = packageElement; - this.simpleName = CodeNames.of(simpleName); - if (this.packageElement != null) { - this.packageName = packageElement.getQualifiedName(); - } else { - this.packageName = CodeNames.of("default"); - } - this.qualifiedName = createQualifiedName(); - } - - @Override - public TypeMirror asType() { - return mirror; - } - - @Override - public ElementKind getKind() { - return kind; - } - - public boolean containsField(String name) { - for (VariableElement field : getFields()) { - if (field.getSimpleName().toString().equals(name)) { - return true; - } - } - return false; - } - - @Override - public NestingKind getNestingKind() { - return isTopLevelClass() ? NestingKind.TOP_LEVEL : NestingKind.LOCAL; - } - - @Override - public Element getEnclosingElement() { - if (isTopLevelClass()) { - return packageElement; - } else { - return super.getEnclosingElement(); - } - } - - @Override - public TypeMirror getSuperclass() { - return superClass; - } - - @Override - public List getInterfaces() { - return implementsInterfaces; - } - - @Override - public List getTypeParameters() { - return Collections.emptyList(); - } - - public boolean isTopLevelClass() { - return super.getEnclosingElement() instanceof CodeCompilationUnit; - } - - public CodeVariableElement getField(String name) { - for (VariableElement field : ElementFilter.fieldsIn(getEnclosedElements())) { - if (field.getSimpleName().toString().equals(name)) { - return (CodeVariableElement) field; - } - } - return null; - } - - private Name createQualifiedName() { - TypeElement enclosingType = getEnclosingClass(); - if (enclosingType == null) { - return CodeNames.of(packageName + "." + simpleName); - } else { - return CodeNames.of(enclosingType.getQualifiedName() + "." + simpleName); - } - } - - @Override - void setEnclosingElement(Element element) { - super.setEnclosingElement(element); - - // update qualified name on container change - this.qualifiedName = createQualifiedName(); - } - - public Name getPackageName() { - return packageName; - } - - @Override - public Name getQualifiedName() { - return qualifiedName; - } - - @Override - public Name getSimpleName() { - return simpleName; - } - - public void setSuperClass(TypeMirror superType) { - this.superClass = superType; - } - - public List getImports() { - return imports; - } - - public List getImplements() { - return implementsInterfaces; - } - - @Override - public int hashCode() { - return getQualifiedName().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (obj instanceof TypeElement) { - return getQualifiedName().equals(((TypeElement) obj).getQualifiedName()); - } - return false; - } - - public List getFields() { - return ElementFilter.fieldsIn(getEnclosedElements()); - } - - public ExecutableElement getMethod(String name) { - for (Element element : getEnclosedElements()) { - if (element.getKind() == ElementKind.METHOD && element.getSimpleName().toString().equals(name)) { - return (ExecutableElement) element; - } - } - return null; - } - - public List getMethods() { - return ElementFilter.methodsIn(getEnclosedElements()); - } - - public List getInnerClasses() { - return ElementFilter.typesIn(getEnclosedElements()); - } - - @Override - public String toString() { - return getQualifiedName().toString(); - } - - @Override - public R accept(ElementVisitor v, P p) { - return v.visitType(this, p); - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +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.codegen.processor.ast; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -public class CodeTypeMirror implements TypeMirror { - - private final TypeKind kind; - - public CodeTypeMirror(TypeKind kind) { - this.kind = kind; - } - - @Override - public TypeKind getKind() { - return kind; - } - - @Override - public R accept(TypeVisitor v, P p) { - throw new UnsupportedOperationException(); - } - - public static class ArrayCodeTypeMirror extends CodeTypeMirror implements ArrayType { - - private final TypeMirror component; - - public ArrayCodeTypeMirror(TypeMirror component) { - super(TypeKind.ARRAY); - this.component = component; - } - - @Override - public TypeMirror getComponentType() { - return component; - } - - } - - public static class DeclaredCodeTypeMirror extends CodeTypeMirror implements DeclaredType { - - private final TypeElement clazz; - private final List typeArguments; - - public DeclaredCodeTypeMirror(TypeElement clazz) { - this(clazz, Collections. emptyList()); - } - - public DeclaredCodeTypeMirror(TypeElement clazz, List typeArguments) { - super(TypeKind.DECLARED); - this.clazz = clazz; - this.typeArguments = typeArguments; - } - - @Override - public Element asElement() { - return clazz; - } - - @Override - public TypeMirror getEnclosingType() { - return clazz.getEnclosingElement().asType(); - } - - @Override - public List getTypeArguments() { - return typeArguments; - } - - @Override - public String toString() { - return clazz.getQualifiedName().toString(); - } - - } - - public List getAnnotationMirrors() { - throw new UnsupportedOperationException(); - } - - /** - * @param annotationType - */ - public A getAnnotation(Class annotationType) { - throw new UnsupportedOperationException(); - } - - /** - * @param annotationType - */ - public A[] getAnnotationsByType(Class annotationType) { - throw new UnsupportedOperationException(); - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeVariableElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeVariableElement.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +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.codegen.processor.ast; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.api.element.*; - -public final class CodeVariableElement extends CodeElement implements WritableVariableElement { - - private Name name; - private TypeMirror type; - private Object constantValue; - - private CodeTree init; - - public CodeVariableElement(TypeMirror type, String name) { - super(Utils.modifiers()); - this.type = type; - this.name = CodeNames.of(name); - } - - public CodeVariableElement(Set modifiers, TypeMirror type, String name) { - super(modifiers); - this.type = type; - this.name = CodeNames.of(name); - } - - public CodeVariableElement(Set modifiers, TypeMirror type, String name, String init) { - this(modifiers, type, name); - if (init != null) { - this.init = new CodeTree(CodeTreeKind.STRING, null, init); - } - } - - public CodeTreeBuilder createInitBuilder() { - CodeTreeBuilder builder = new CodeTreeBuilder(null); - init = builder.getTree(); - init.setEnclosingElement(this); - return builder; - } - - public void setInit(CodeTree init) { - this.init = init; - } - - public CodeTree getInit() { - return init; - } - - public Name getSimpleName() { - return name; - } - - public TypeMirror getType() { - return type; - } - - @Override - public TypeMirror asType() { - return type; - } - - @Override - public ElementKind getKind() { - if (getEnclosingElement() instanceof ExecutableElement) { - return ElementKind.PARAMETER; - } else if (getEnclosingElement() instanceof TypeElement) { - return ElementKind.FIELD; - } else { - return ElementKind.PARAMETER; - } - } - - public void setConstantValue(Object constantValue) { - this.constantValue = constantValue; - } - - @Override - public Object getConstantValue() { - return constantValue; - } - - public String getName() { - return getSimpleName().toString(); - } - - @Override - public void setSimpleName(Name name) { - this.name = name; - } - - public void setName(String name) { - this.name = CodeNames.of(name); - } - - @Override - public void setType(TypeMirror type) { - this.type = type; - } - - @Override - public R accept(ElementVisitor v, P p) { - return v.visitVariable(this, p); - } - - public static CodeVariableElement clone(VariableElement var) { - CodeVariableElement copy = new CodeVariableElement(var.getModifiers(), var.asType(), var.getSimpleName().toString()); - copy.setConstantValue(var.getConstantValue()); - for (AnnotationMirror mirror : var.getAnnotationMirrors()) { - copy.addAnnotationMirror(mirror); - } - for (Element element : var.getEnclosedElements()) { - copy.add(element); - } - return copy; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/GeneratedElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/GeneratedElement.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +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.codegen.processor.ast; - -import javax.lang.model.element.*; - -public interface GeneratedElement { - - AnnotationMirror getGeneratorAnnotationMirror(); - - void setGeneratorAnnotationMirror(AnnotationMirror mirror); - - Element getGeneratorElement(); - - void setGeneratorElement(Element element); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,705 +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.codegen.processor.codewriter; - -import static com.oracle.truffle.codegen.processor.Utils.*; - -import java.io.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.ast.*; - -public abstract class AbstractCodeWriter extends CodeElementScanner { - - private static final int LINE_LENGTH = 200; - private static final int LINE_WRAP_INDENTS = 3; - private static final String IDENT_STRING = " "; - private static final String LN = "\n"; /* unix style */ - - protected Writer writer; - private int indent; - private boolean newLine; - private int lineLength; - private boolean lineWrapping = false; - - private OrganizedImports imports; - - public void visitCompilationUnit(CodeCompilationUnit e) { - for (TypeElement clazz : e.getEnclosedElements()) { - clazz.accept(this, null); - } - } - - protected abstract Writer createWriter(CodeTypeElement clazz) throws IOException; - - @Override - public Void visitType(CodeTypeElement e, Void p) { - if (e.isTopLevelClass()) { - Writer w = null; - try { - imports = OrganizedImports.organize(e); - w = new TrimTrailingSpaceWriter(createWriter(e)); - writer = w; - writeRootClass(e); - } catch (IOException ex) { - throw new RuntimeException(ex); - } finally { - if (w != null) { - try { - w.close(); - } catch (Throwable e1) { - // see eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=361378 - // TODO temporary suppress errors on close. - } - } - writer = null; - } - } else { - writeClassImpl(e); - } - return null; - } - - private void writeRootClass(CodeTypeElement e) { - writeHeader(); - write("package ").write(e.getPackageName()).write(";").writeLn(); - writeEmptyLn(); - - Set generateImports = imports.generateImports(); - List typeImports = new ArrayList<>(); - List staticImports = new ArrayList<>(); - - for (CodeImport codeImport : generateImports) { - if (codeImport.isStaticImport()) { - staticImports.add(codeImport); - } else { - typeImports.add(codeImport); - } - } - Collections.sort(typeImports); - Collections.sort(staticImports); - - for (CodeImport imp : staticImports) { - imp.accept(this, null); - writeLn(); - } - if (!staticImports.isEmpty()) { - writeEmptyLn(); - } - - for (CodeImport imp : typeImports) { - imp.accept(this, null); - writeLn(); - } - if (!typeImports.isEmpty()) { - writeEmptyLn(); - } - - writeClassImpl(e); - } - - private String useImport(Element enclosedType, TypeMirror type) { - if (imports != null) { - return imports.createTypeReference(enclosedType, type); - } else { - return Utils.getSimpleName(type); - } - } - - private void writeClassImpl(CodeTypeElement e) { - for (AnnotationMirror annotation : e.getAnnotationMirrors()) { - visitAnnotation(e, annotation); - writeLn(); - } - - writeModifiers(e.getModifiers()); - if (e.getKind() == ElementKind.ENUM) { - write("enum "); - } else { - write("class "); - } - write(e.getSimpleName()); - if (e.getSuperclass() != null && !getQualifiedName(e.getSuperclass()).equals("java.lang.Object")) { - write(" extends ").write(useImport(e, e.getSuperclass())); - } - if (e.getImplements().size() > 0) { - write(" implements "); - for (int i = 0; i < e.getImplements().size(); i++) { - write(useImport(e, e.getImplements().get(i))); - if (i < e.getImplements().size() - 1) { - write(", "); - } - } - } - - write(" {").writeLn(); - writeEmptyLn(); - indent(1); - - List staticFields = getStaticFields(e); - List instanceFields = getInstanceFields(e); - - for (int i = 0; i < staticFields.size(); i++) { - VariableElement field = staticFields.get(i); - field.accept(this, null); - if (e.getKind() == ElementKind.ENUM && i < staticFields.size() - 1) { - write(","); - writeLn(); - } else { - write(";"); - writeLn(); - } - } - - if (staticFields.size() > 0) { - writeEmptyLn(); - } - - for (VariableElement field : instanceFields) { - field.accept(this, null); - write(";"); - writeLn(); - } - if (instanceFields.size() > 0) { - writeEmptyLn(); - } - - for (ExecutableElement method : ElementFilter.constructorsIn(e.getEnclosedElements())) { - method.accept(this, null); - } - - for (ExecutableElement method : getInstanceMethods(e)) { - method.accept(this, null); - } - - for (ExecutableElement method : getStaticMethods(e)) { - method.accept(this, null); - } - - for (TypeElement clazz : e.getInnerClasses()) { - clazz.accept(this, null); - } - - dedent(1); - write("}"); - writeEmptyLn(); - } - - private static List getStaticFields(CodeTypeElement clazz) { - List staticFields = new ArrayList<>(); - for (VariableElement field : clazz.getFields()) { - if (field.getModifiers().contains(Modifier.STATIC)) { - staticFields.add(field); - } - } - return staticFields; - } - - private static List getInstanceFields(CodeTypeElement clazz) { - List instanceFields = new ArrayList<>(); - for (VariableElement field : clazz.getFields()) { - if (!field.getModifiers().contains(Modifier.STATIC)) { - instanceFields.add(field); - } - } - return instanceFields; - } - - private static List getStaticMethods(CodeTypeElement clazz) { - List staticMethods = new ArrayList<>(); - for (ExecutableElement method : clazz.getMethods()) { - if (method.getModifiers().contains(Modifier.STATIC)) { - staticMethods.add(method); - } - } - return staticMethods; - } - - private static List getInstanceMethods(CodeTypeElement clazz) { - List instanceMethods = new ArrayList<>(); - for (ExecutableElement method : clazz.getMethods()) { - if (!method.getModifiers().contains(Modifier.STATIC)) { - instanceMethods.add(method); - } - } - return instanceMethods; - } - - @Override - public Void visitVariable(VariableElement f, Void p) { - Element parent = f.getEnclosingElement(); - - for (AnnotationMirror annotation : f.getAnnotationMirrors()) { - visitAnnotation(f, annotation); - write(" "); - } - - CodeTree init = null; - if (f instanceof CodeVariableElement) { - init = ((CodeVariableElement) f).getInit(); - } - - if (parent.getKind() == ElementKind.ENUM && f.getModifiers().contains(Modifier.STATIC)) { - write(f.getSimpleName()); - if (init != null) { - if (init != null) { - write("("); - init.acceptCodeElementScanner(this, p); - write(")"); - } - } - } else { - writeModifiers(f.getModifiers()); - write(useImport(f, f.asType())); - - if (f.getEnclosingElement().getKind() == ElementKind.METHOD) { - ExecutableElement method = (ExecutableElement) f.getEnclosingElement(); - if (method.isVarArgs() && method.getParameters().indexOf(f) == method.getParameters().size() - 1) { - write("..."); - } - } - - write(" "); - write(f.getSimpleName()); - if (init != null) { - write(" = "); - init.acceptCodeElementScanner(this, p); - } - } - return null; - } - - public void visitAnnotation(Element enclosedElement, AnnotationMirror e) { - write("@").write(useImport(enclosedElement, e.getAnnotationType())); - - if (!e.getElementValues().isEmpty()) { - write("("); - final ExecutableElement defaultElement = findExecutableElement(e.getAnnotationType(), "value"); - - Map values = e.getElementValues(); - if (defaultElement != null && values.size() == 1 && values.get(defaultElement) != null) { - visitAnnotationValue(enclosedElement, values.get(defaultElement)); - } else { - Set methodsSet = values.keySet(); - List methodsList = new ArrayList<>(); - for (ExecutableElement method : methodsSet) { - if (values.get(method) == null) { - continue; - } - methodsList.add(method); - } - - Collections.sort(methodsList, new Comparator() { - - @Override - public int compare(ExecutableElement o1, ExecutableElement o2) { - return o1.getSimpleName().toString().compareTo(o2.getSimpleName().toString()); - } - }); - - for (int i = 0; i < methodsList.size(); i++) { - ExecutableElement method = methodsList.get(i); - AnnotationValue value = values.get(method); - write(method.getSimpleName().toString()); - write(" = "); - visitAnnotationValue(enclosedElement, value); - - if (i < methodsList.size() - 1) { - write(", "); - } - } - } - - write(")"); - } - } - - public void visitAnnotationValue(Element enclosedElement, AnnotationValue e) { - e.accept(new AnnotationValueWriterVisitor(enclosedElement), null); - } - - private class AnnotationValueWriterVisitor extends AbstractAnnotationValueVisitor7 { - - private final Element enclosedElement; - - public AnnotationValueWriterVisitor(Element enclosedElement) { - this.enclosedElement = enclosedElement; - } - - @Override - public Void visitBoolean(boolean b, Void p) { - write(Boolean.toString(b)); - return null; - } - - @Override - public Void visitByte(byte b, Void p) { - write(Byte.toString(b)); - return null; - } - - @Override - public Void visitChar(char c, Void p) { - write(Character.toString(c)); - return null; - } - - @Override - public Void visitDouble(double d, Void p) { - write(Double.toString(d)); - return null; - } - - @Override - public Void visitFloat(float f, Void p) { - write(Float.toString(f)); - return null; - } - - @Override - public Void visitInt(int i, Void p) { - write(Integer.toString(i)); - return null; - } - - @Override - public Void visitLong(long i, Void p) { - write(Long.toString(i)); - return null; - } - - @Override - public Void visitShort(short s, Void p) { - write(Short.toString(s)); - return null; - } - - @Override - public Void visitString(String s, Void p) { - write("\""); - write(s); - write("\""); - return null; - } - - @Override - public Void visitType(TypeMirror t, Void p) { - write(useImport(enclosedElement, t)); - write(".class"); - return null; - } - - @Override - public Void visitEnumConstant(VariableElement c, Void p) { - write(useImport(enclosedElement, c.asType())); - write("."); - write(c.getSimpleName().toString()); - return null; - } - - @Override - public Void visitAnnotation(AnnotationMirror a, Void p) { - AbstractCodeWriter.this.visitAnnotation(enclosedElement, a); - return null; - } - - @Override - public Void visitArray(List vals, Void p) { - write("{"); - for (int i = 0; i < vals.size(); i++) { - AnnotationValue value = vals.get(i); - AbstractCodeWriter.this.visitAnnotationValue(enclosedElement, value); - if (i < vals.size() - 1) { - write(", "); - } - } - write("}"); - return null; - } - } - - public ExecutableElement findExecutableElement(DeclaredType type, String name) { - List elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements()); - for (ExecutableElement executableElement : elements) { - if (executableElement.getSimpleName().toString().equals(name)) { - return executableElement; - } - } - return null; - } - - @Override - public void visitImport(CodeImport e, Void p) { - if (e.isStaticImport()) { - write("import static ").write(e.getImportString()).write(";"); - } else { - write("import ").write(e.getImportString()).write(";"); - } - } - - @Override - public Void visitExecutable(CodeExecutableElement e, Void p) { - for (AnnotationMirror annotation : e.getAnnotationMirrors()) { - visitAnnotation(e, annotation); - writeLn(); - } - - writeModifiers(e.getModifiers()); - - if (e.getReturnType() != null) { - write(useImport(e, e.getReturnType())); - write(" "); - } - write(e.getSimpleName()); - write("("); - - for (int i = 0; i < e.getParameters().size(); i++) { - VariableElement param = e.getParameters().get(i); - param.accept(this, p); - if (i < e.getParameters().size() - 1) { - write(", "); - } - } - write(")"); - - List throwables = e.getThrownTypes(); - if (throwables.size() > 0) { - write(" throws "); - for (int i = 0; i < throwables.size(); i++) { - write(useImport(e, throwables.get(i))); - if (i < throwables.size() - 1) { - write(", "); - } - } - } - - if (e.getModifiers().contains(Modifier.ABSTRACT)) { - writeLn(";"); - } else if (e.getBodyTree() != null) { - writeLn(" {"); - indent(1); - e.getBodyTree().acceptCodeElementScanner(this, p); - dedent(1); - writeLn("}"); - } else if (e.getBody() != null) { - write(" {"); - write(e.getBody()); - writeLn("}"); - } else { - writeLn("{ }"); - } - writeEmptyLn(); - return null; - } - - @Override - public void visitTree(CodeTree e, Void p) { - CodeTreeKind kind = e.getCodeKind(); - - switch (kind) { - case COMMA_GROUP: - List children = e.getEnclosedElements(); - for (int i = 0; i < children.size(); i++) { - children.get(i).acceptCodeElementScanner(this, p); - if (i < e.getEnclosedElements().size() - 1) { - write(", "); - } - } - break; - case GROUP: - for (CodeTree tree : e.getEnclosedElements()) { - tree.acceptCodeElementScanner(this, p); - } - break; - case INDENT: - indent(1); - for (CodeTree tree : e.getEnclosedElements()) { - tree.acceptCodeElementScanner(this, p); - } - dedent(1); - break; - case NEW_LINE: - writeLn(); - break; - case STRING: - if (e.getString() != null) { - write(e.getString()); - } else { - write("null"); - } - break; - case STATIC_FIELD_REFERENCE: - if (e.getString() != null) { - write(imports.createStaticFieldReference(e, e.getType(), e.getString())); - } else { - write("null"); - } - break; - case STATIC_METHOD_REFERENCE: - if (e.getString() != null) { - write(imports.createStaticMethodReference(e, e.getType(), e.getString())); - } else { - write("null"); - } - break; - case TYPE: - write(useImport(e, e.getType())); - break; - default: - assert false; - return; - } - } - - protected void writeHeader() { - // default implementation does nothing - } - - private void writeModifiers(Set modifiers) { - if (modifiers != null) { - for (Modifier modifier : modifiers) { - write(modifier.toString()); - write(" "); - } - } - } - - protected void indent(int count) { - indent += count; - } - - protected void dedent(int count) { - indent -= count; - } - - protected void writeLn() { - writeLn(""); - } - - protected void writeLn(String text) { - write(text); - write(LN); - lineLength = 0; - newLine = true; - if (lineWrapping) { - dedent(LINE_WRAP_INDENTS); - lineWrapping = false; - } - lineWrapping = false; - } - - protected void writeEmptyLn() { - writeLn(); - } - - private AbstractCodeWriter write(Name name) { - return write(name.toString()); - } - - private AbstractCodeWriter write(String m) { - try { - lineLength += m.length(); - if (newLine && m != LN) { - writeIndent(); - newLine = false; - } - if (lineLength > LINE_LENGTH && m.length() > 0) { - char firstChar = m.charAt(0); - if (Character.isAlphabetic(firstChar)) { - if (!lineWrapping) { - indent(LINE_WRAP_INDENTS); - } - lineWrapping = true; - lineLength = 0; - write(LN); - writeIndent(); - } - } - writer.write(m); - } catch (IOException e) { - throw new RuntimeException(e); - } - return this; - } - - private void writeIndent() throws IOException { - for (int i = 0; i < indent; i++) { - lineLength += IDENT_STRING.length(); - writer.write(IDENT_STRING); - } - } - - private static class TrimTrailingSpaceWriter extends Writer { - - private final Writer delegate; - private final StringBuilder buffer = new StringBuilder(); - - public TrimTrailingSpaceWriter(Writer delegate) { - this.delegate = delegate; - } - - @Override - public void close() throws IOException { - this.delegate.close(); - } - - @Override - public void flush() throws IOException { - this.delegate.flush(); - } - - @Override - public void write(char[] cbuf, int off, int len) throws IOException { - buffer.append(cbuf, off, len); - int newLinePoint = buffer.indexOf(LN); - - if (newLinePoint != -1) { - String lhs = trimTrailing(buffer.substring(0, newLinePoint)); - delegate.write(lhs); - delegate.write(LN); - buffer.delete(0, newLinePoint + 1); - } - } - - private static String trimTrailing(String s) { - int cut = 0; - for (int i = s.length() - 1; i >= 0; i--) { - if (Character.isWhitespace(s.charAt(i))) { - cut++; - } else { - break; - } - } - if (cut > 0) { - return s.substring(0, s.length() - cut); - } - return s; - } - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/FixWarningsVisitor.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/FixWarningsVisitor.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +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.codegen.processor.codewriter; - -import static com.oracle.truffle.codegen.processor.Utils.*; -import static javax.lang.model.element.Modifier.*; - -import java.io.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.ast.*; - -public class FixWarningsVisitor extends CodeElementScanner { - - private final Set symbolsUsed = new HashSet<>(); - - private final ProcessorContext context; - private final DeclaredType unusedAnnotation; - private final DeclaredType overrideType; - - public FixWarningsVisitor(ProcessorContext context, DeclaredType unusedAnnotation, DeclaredType overrideType) { - this.context = context; - this.unusedAnnotation = unusedAnnotation; - this.overrideType = overrideType; - } - - @Override - public Void visitType(CodeTypeElement e, Void p) { - List superTypes = Utils.getSuperTypes(e); - for (TypeElement type : superTypes) { - String qualifiedName = Utils.getQualifiedName(type); - if (qualifiedName.equals(Serializable.class.getCanonicalName())) { - if (!e.containsField("serialVersionUID")) { - e.add(new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), context.getType(long.class), "serialVersionUID", "1L")); - } - break; - } - } - - return super.visitType(e, p); - } - - @Override - public Void visitExecutable(CodeExecutableElement e, Void p) { - if (e.getParameters().isEmpty()) { - return null; - } else if (e.getModifiers().contains(Modifier.ABSTRACT)) { - return null; - } else if (containsOverride(e)) { - return null; - } - - symbolsUsed.clear(); - super.visitExecutable(e, p); - if (e.getBodyTree() == null && e.getBody() != null) { - computeSymbols(e.getBody()); - } - - for (VariableElement parameter : e.getParameters()) { - if (!symbolsUsed.contains(parameter.getSimpleName().toString())) { - e.getAnnotationMirrors().add(createUnusedAnnotationMirror()); - break; - } - } - return null; - } - - private boolean containsOverride(CodeExecutableElement e) { - for (AnnotationMirror mirror : e.getAnnotationMirrors()) { - if (Utils.typeEquals(overrideType, mirror.getAnnotationType())) { - return true; - } - } - return false; - } - - private CodeAnnotationMirror createUnusedAnnotationMirror() { - CodeAnnotationMirror mirror = new CodeAnnotationMirror(unusedAnnotation); - mirror.setElementValue(mirror.findExecutableElement("value"), new CodeAnnotationValue("unused")); - return mirror; - } - - @Override - public void visitTree(CodeTree e, Void p) { - if (e.getString() != null) { - computeSymbols(e.getString()); - } - super.visitTree(e, p); - } - - private void computeSymbols(String s) { - // TODO there should not be any need for a StringTokenizer if we have a real AST for - // method bodies. Also the current solution is not perfect. What if one token - // is spread across multiple CodeTree instances? But for now that works. - StringTokenizer tokenizer = new StringTokenizer(s, ".= :,()[];{}\"\"'' ", false); - while (tokenizer.hasMoreElements()) { - String token = tokenizer.nextToken().trim(); - if (token.length() > 0) { - symbolsUsed.add(token); - } - } - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/GenerateOverrideVisitor.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/GenerateOverrideVisitor.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +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.codegen.processor.codewriter; - -import static com.oracle.truffle.codegen.processor.Utils.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.ast.*; - -public class GenerateOverrideVisitor extends CodeElementScanner { - - private final DeclaredType overrideType; - - public GenerateOverrideVisitor(DeclaredType overrideType) { - this.overrideType = overrideType; - } - - @Override - public Void visitExecutable(CodeExecutableElement e, Void p) { - if (!e.getModifiers().contains(Modifier.STATIC) && !e.getModifiers().contains(Modifier.PRIVATE)) { - String name = e.getSimpleName().toString(); - TypeMirror[] params = e.getParameterTypes(); - - for (AnnotationMirror mirror : e.getAnnotationMirrors()) { - if (Utils.typeEquals(overrideType, mirror.getAnnotationType())) { - // already declared (may happen if method copied from super class) - return super.visitExecutable(e, p); - } - } - - if (isDeclaredMethodInSuperType(e.getEnclosingClass(), name, params)) { - e.addAnnotationMirror(new CodeAnnotationMirror(overrideType)); - } - } - return super.visitExecutable(e, p); - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,491 +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.codegen.processor.codewriter; - -import static com.oracle.truffle.codegen.processor.Utils.*; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.ast.*; - -public final class OrganizedImports { - - private final Set staticImportUsage = new HashSet<>(); - - private final Map simpleNamesUsed = new HashMap<>(); - - private final Set declaredStaticMethods = new HashSet<>(); - private final Set declaredStaticFields = new HashSet<>(); - private final Set ambiguousStaticMethods = new HashSet<>(); - private final Set ambiguousStaticFields = new HashSet<>(); - - private final CodeTypeElement topLevelClass; - - private OrganizedImports(CodeTypeElement topLevelClass) { - this.topLevelClass = topLevelClass; - } - - public static OrganizedImports organize(CodeTypeElement topLevelClass) { - OrganizedImports organized = new OrganizedImports(topLevelClass); - organized.organizeImpl(); - return organized; - } - - private void organizeImpl() { - ImportTypeReferenceVisitor reference = new ImportTypeReferenceVisitor(); - topLevelClass.accept(reference, null); - - processStaticImports(topLevelClass); - List types = Utils.getSuperTypes(topLevelClass); - for (TypeElement typeElement : types) { - processStaticImports(typeElement); - } - - for (TypeMirror type : staticImportUsage) { - TypeElement element = fromTypeMirror(type); - if (element != null) { - // already processed by supertype - if (types.contains(element)) { - continue; - } - processStaticImports(element); - } - } - } - - public String createTypeReference(Element enclosedElement, TypeMirror type) { - switch (type.getKind()) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FLOAT: - case SHORT: - case INT: - case LONG: - case VOID: - return Utils.getSimpleName(type); - case DECLARED: - return createDeclaredTypeName(enclosedElement, (DeclaredType) type); - case ARRAY: - return createTypeReference(enclosedElement, ((ArrayType) type).getComponentType()) + "[]"; - case WILDCARD: - return createWildcardName(enclosedElement, (WildcardType) type); - case TYPEVAR: - return "?"; - default: - throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type); - } - } - - public String createStaticFieldReference(Element enclosedElement, TypeMirror type, String fieldName) { - return createStaticReference(enclosedElement, type, fieldName, ambiguousStaticFields, declaredStaticFields); - } - - public String createStaticMethodReference(Element enclosedElement, TypeMirror type, String methodName) { - return createStaticReference(enclosedElement, type, methodName, ambiguousStaticMethods, declaredStaticMethods); - } - - private String createStaticReference(Element enclosedElement, TypeMirror type, String name, Set ambiguousSymbols, Set declaredSymbols) { - if (ambiguousSymbols.contains(name)) { - // ambiguous import - return createTypeReference(enclosedElement, type) + "." + name; - } else if (!declaredSymbols.contains(name)) { - // not imported at all - return createTypeReference(enclosedElement, type) + "." + name; - } else { - // import declared and not ambiguous - return name; - } - } - - private String createWildcardName(Element enclosedElement, WildcardType type) { - StringBuilder b = new StringBuilder(); - if (type.getExtendsBound() != null) { - b.append("? extends ").append(createTypeReference(enclosedElement, type.getExtendsBound())); - } else if (type.getSuperBound() != null) { - b.append("? super ").append(createTypeReference(enclosedElement, type.getExtendsBound())); - } - return b.toString(); - } - - private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) { - String name = type.asElement().getSimpleName().toString(); - - if (needsImport(enclosedElement, type)) { - TypeMirror usedByType = simpleNamesUsed.get(name); - if (usedByType == null) { - simpleNamesUsed.put(name, type); - usedByType = type; - } - - if (!typeEquals(type, usedByType)) { - name = getQualifiedName(type); - } - } - - if (type.getTypeArguments().size() == 0) { - return name; - } - - StringBuilder b = new StringBuilder(name); - b.append("<"); - if (type.getTypeArguments().size() > 0) { - for (int i = 0; i < type.getTypeArguments().size(); i++) { - b.append(createTypeReference(enclosedElement, type.getTypeArguments().get(i))); - if (i < type.getTypeArguments().size() - 1) { - b.append(", "); - } - } - } - b.append(">"); - return b.toString(); - } - - public Set generateImports() { - Set imports = new HashSet<>(); - - imports.addAll(generateImports(simpleNamesUsed.values())); - imports.addAll(generateStaticImports(staticImportUsage)); - - return imports; - } - - boolean processStaticImports(TypeElement element) { - Set importedMethods = new HashSet<>(); - List methods = ElementFilter.methodsIn(element.getEnclosedElements()); - for (ExecutableElement method : methods) { - if (method.getModifiers().contains(Modifier.STATIC)) { - importedMethods.add(method.getSimpleName().toString()); - } - } - - boolean allMethodsAmbiguous = processStaticImportElements(importedMethods, this.ambiguousStaticMethods, this.declaredStaticMethods); - - Set importedFields = new HashSet<>(); - List fields = ElementFilter.fieldsIn(element.getEnclosedElements()); - for (VariableElement field : fields) { - if (field.getModifiers().contains(Modifier.STATIC)) { - importedFields.add(field.getSimpleName().toString()); - } - } - - boolean allFieldsAmbiguous = processStaticImportElements(importedFields, this.ambiguousStaticFields, this.declaredStaticFields); - - return allMethodsAmbiguous && allFieldsAmbiguous; - } - - private static boolean processStaticImportElements(Set newElements, Set ambiguousElements, Set declaredElements) { - boolean allAmbiguous = false; - if (declaredElements.containsAll(newElements)) { - // all types already declared -> we can remove the import completely -> they will all - // get ambiguous - allAmbiguous = true; - } - Set newAmbiguous = new HashSet<>(); - Set newDeclared = new HashSet<>(); - - for (String newElement : newElements) { - if (declaredElements.contains(newElement)) { - newAmbiguous.add(newElement); - } else if (ambiguousElements.contains(newElement)) { - // nothing to do - } else { - newDeclared.add(newElement); - } - } - - ambiguousElements.addAll(newAmbiguous); - declaredElements.addAll(newDeclared); - return allAmbiguous; - } - - private boolean needsImport(Element enclosedElement, TypeMirror importType) { - String importPackagName = getPackageName(importType); - if (importPackagName == null) { - return false; - } else if (importPackagName.equals("java.lang")) { - return false; - } else if (importPackagName.equals(getPackageName(topLevelClass)) && Utils.isTopLevelClass(importType)) { - return false; // same package name -> no import - } - - List elements = Utils.getElementHierarchy(enclosedElement); - - Set autoImportedTypes = new HashSet<>(); - for (Element element : elements) { - if (element.getKind().isClass()) { - collectSuperTypeImports((TypeElement) element, autoImportedTypes); - collectInnerTypeImports((TypeElement) element, autoImportedTypes); - } - } - - String qualifiedName = getQualifiedName(importType); - if (autoImportedTypes.contains(qualifiedName)) { - return false; - } - - return true; - } - - private static Set generateImports(Collection toGenerate) { - TreeSet importObjects = new TreeSet<>(); - for (TypeMirror importType : toGenerate) { - importObjects.add(new CodeImport(importType, getQualifiedName(importType), false)); - } - return importObjects; - } - - private static void collectInnerTypeImports(TypeElement e, Set autoImportedTypes) { - autoImportedTypes.add(getQualifiedName(e)); - for (TypeElement innerClass : ElementFilter.typesIn(e.getEnclosedElements())) { - collectInnerTypeImports(innerClass, autoImportedTypes); - } - } - - private static void collectSuperTypeImports(TypeElement e, Set autoImportedTypes) { - List superTypes = getSuperTypes(e); - for (TypeElement superType : superTypes) { - List declaredTypes = getDeclaredTypes(superType); - for (TypeElement declaredType : declaredTypes) { - autoImportedTypes.add(getQualifiedName(declaredType)); - } - } - } - - private Set generateStaticImports(Set toGenerate) { - Set autoImportedStaticTypes = new HashSet<>(); - - // if type is declared inside a super type of this class -> no import - autoImportedStaticTypes.add(getQualifiedName(topLevelClass)); - autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(topLevelClass)); - - TreeSet importObjects = new TreeSet<>(); - for (TypeMirror importType : toGenerate) { - if (getPackageName(importType) == null) { - continue; // no package name -> no import - } - - String qualifiedName = getQualifiedName(importType); - if (autoImportedStaticTypes.contains(qualifiedName)) { - continue; - } - - importObjects.add(new CodeImport(importType, qualifiedName + ".*", true)); - } - - return importObjects; - } - - private abstract static class TypeReferenceVisitor extends CodeElementScanner { - - @Override - public void visitTree(CodeTree e, Void p) { - if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) { - visitStaticFieldReference(e, e.getType(), e.getString()); - } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) { - visitStaticMethodReference(e, e.getType(), e.getString()); - } else if (e.getType() != null) { - visitTypeReference(e, e.getType()); - } - super.visitTree(e, p); - } - - @Override - public Void visitExecutable(CodeExecutableElement e, Void p) { - visitAnnotations(e, e.getAnnotationMirrors()); - if (e.getReturnType() != null) { - visitTypeReference(e, e.getReturnType()); - } - for (TypeMirror type : e.getThrownTypes()) { - visitTypeReference(e, type); - } - return super.visitExecutable(e, p); - } - - @Override - public Void visitType(CodeTypeElement e, Void p) { - visitAnnotations(e, e.getAnnotationMirrors()); - - visitTypeReference(e, e.getSuperclass()); - for (TypeMirror type : e.getImplements()) { - visitTypeReference(e, type); - } - - return super.visitType(e, p); - } - - private void visitAnnotations(Element enclosingElement, List mirrors) { - for (AnnotationMirror mirror : mirrors) { - visitAnnotation(enclosingElement, mirror); - } - } - - public void visitAnnotation(Element enclosingElement, AnnotationMirror e) { - visitTypeReference(enclosingElement, e.getAnnotationType()); - if (!e.getElementValues().isEmpty()) { - Map values = e.getElementValues(); - Set methodsSet = values.keySet(); - List methodsList = new ArrayList<>(); - for (ExecutableElement method : methodsSet) { - if (values.get(method) == null) { - continue; - } - methodsList.add(method); - } - - for (int i = 0; i < methodsList.size(); i++) { - AnnotationValue value = values.get(methodsList.get(i)); - visitAnnotationValue(enclosingElement, value); - } - } - } - - public void visitAnnotationValue(Element enclosingElement, AnnotationValue e) { - e.accept(new AnnotationValueReferenceVisitor(enclosingElement), null); - } - - private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7 { - - private final Element enclosingElement; - - public AnnotationValueReferenceVisitor(Element enclosedElement) { - this.enclosingElement = enclosedElement; - } - - @Override - public Void visitBoolean(boolean b, Void p) { - return null; - } - - @Override - public Void visitByte(byte b, Void p) { - return null; - } - - @Override - public Void visitChar(char c, Void p) { - return null; - } - - @Override - public Void visitDouble(double d, Void p) { - return null; - } - - @Override - public Void visitFloat(float f, Void p) { - return null; - } - - @Override - public Void visitInt(int i, Void p) { - return null; - } - - @Override - public Void visitLong(long i, Void p) { - return null; - } - - @Override - public Void visitShort(short s, Void p) { - return null; - } - - @Override - public Void visitString(String s, Void p) { - return null; - } - - @Override - public Void visitType(TypeMirror t, Void p) { - visitTypeReference(enclosingElement, t); - return null; - } - - @Override - public Void visitEnumConstant(VariableElement c, Void p) { - visitTypeReference(enclosingElement, c.asType()); - return null; - } - - @Override - public Void visitAnnotation(AnnotationMirror a, Void p) { - TypeReferenceVisitor.this.visitAnnotation(enclosingElement, a); - return null; - } - - @Override - public Void visitArray(List vals, Void p) { - for (int i = 0; i < vals.size(); i++) { - TypeReferenceVisitor.this.visitAnnotationValue(enclosingElement, vals.get(i)); - } - return null; - } - } - - @Override - public Void visitVariable(VariableElement f, Void p) { - visitAnnotations(f, f.getAnnotationMirrors()); - visitTypeReference(f, f.asType()); - return super.visitVariable(f, p); - } - - @Override - public void visitImport(CodeImport e, Void p) { - } - - public abstract void visitTypeReference(Element enclosedType, TypeMirror type); - - public abstract void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName); - - public abstract void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName); - - } - - private class ImportTypeReferenceVisitor extends TypeReferenceVisitor { - - @Override - public void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName) { - staticImportUsage.add(type); - } - - @Override - public void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName) { - staticImportUsage.add(type); - } - - @Override - public void visitTypeReference(Element enclosedType, TypeMirror type) { - createTypeReference(enclosedType, type); - } - - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/AbstractCompiler.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/AbstractCompiler.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +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.codegen.processor.compiler; - -import java.lang.reflect.*; - -public abstract class AbstractCompiler implements Compiler { - - protected static Object method(Object o, String methodName) throws Exception { - Method method = o.getClass().getMethod(methodName); - method.setAccessible(true); - return method.invoke(o); - } - - protected static Object method(Object o, String methodName, Class[] paramTypes, Object... values) throws Exception { - Method method = o.getClass().getMethod(methodName, paramTypes); - method.setAccessible(true); - return method.invoke(o, values); - } - - protected static Object field(Object o, String fieldName) throws Exception { - if (o == null) { - return null; - } - Field field = o.getClass().getField(fieldName); - field.setAccessible(true); - return field.get(o); - } - - protected static String parseHeader(String content) { - int index = content.indexOf("/*"); - if (index == -1) { - return null; - } - if (!content.substring(0, index).trim().equals("")) { - // just whitespace before - return null; - } - - int endIndex = content.indexOf("*/", index); - if (endIndex == -1) { - return null; - } - return content.substring(index, endIndex + 2); - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/Compiler.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/Compiler.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +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.codegen.processor.compiler; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; - -public interface Compiler { - - String getMethodBody(ProcessingEnvironment env, ExecutableElement method); - - String getHeaderComment(ProcessingEnvironment env, Element type); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/CompilerFactory.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/CompilerFactory.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +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.codegen.processor.compiler; - -import javax.lang.model.element.*; - -public class CompilerFactory { - - private static Compiler javac; - private static Compiler jdt; - - public static Compiler getCompiler(Element currentElement) { - if (JavaCCompiler.isValidElement(currentElement)) { - if (javac == null) { - javac = new JavaCCompiler(); - } - return javac; - } else if (JDTCompiler.isValidElement(currentElement)) { - if (jdt == null) { - jdt = new JDTCompiler(); - } - return jdt; - } else { - throw new UnsupportedOperationException("Unsupported compiler for element " + currentElement.getClass().getName() + "."); - } - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JDTCompiler.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JDTCompiler.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +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.codegen.processor.compiler; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; - -import com.oracle.truffle.codegen.processor.*; - -public class JDTCompiler extends AbstractCompiler { - - public static boolean isValidElement(Element currentElement) { - try { - Class elementClass = Class.forName("org.eclipse.jdt.internal.compiler.apt.model.ElementImpl"); - return elementClass.isAssignableFrom(currentElement.getClass()); - } catch (ClassNotFoundException e) { - return false; - } - } - - @Override - public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { - try { - - char[] source = getSource(method); - if (source == null) { - return null; - } - - /* - * AbstractMethodDeclaration decl = - * ((MethodBinding)(((ElementImpl)method)._binding)).sourceMethod(); int bodyStart = - * decl.bodyStart; int bodyEnd = decl.bodyEnd; - */ - Object decl = method(field(method, "_binding"), "sourceMethod"); - int bodyStart = (int) field(decl, "bodyStart"); - int bodyEnd = (int) field(decl, "bodyEnd"); - - int length = bodyEnd - bodyStart; - char[] target = new char[length]; - System.arraycopy(source, bodyStart, target, 0, length); - - return new String(target); - } catch (Exception e) { - return Utils.printException(e); - } - } - - private static char[] getSource(Element element) throws Exception { - /* - * Binding binding = ((ElementImpl)element)._binding; char[] source = null; if (binding - * instanceof MethodBinding) { source = ((MethodBinding) - * binding).sourceMethod().compilationResult.getCompilationUnit().getContents(); } else if - * (binding instanceof SourceTypeBinding) { source = - * ((SourceTypeBinding)binding).scope.referenceContext - * .compilationResult.compilationUnit.getContents(); } return source; - */ - - Object binding = field(element, "_binding"); - Class methodBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.MethodBinding"); - Class referenceBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding"); - - char[] source = null; - if (methodBindingClass.isAssignableFrom(binding.getClass())) { - Object sourceMethod = method(binding, "sourceMethod"); - if (sourceMethod == null) { - return null; - } - source = (char[]) method(method(field(sourceMethod, "compilationResult"), "getCompilationUnit"), "getContents"); - } else if (referenceBindingClass.isAssignableFrom(binding.getClass())) { - source = (char[]) method(field(field(field(field(binding, "scope"), "referenceContext"), "compilationResult"), "compilationUnit"), "getContents"); - } - return source; - } - - @Override - public String getHeaderComment(ProcessingEnvironment env, Element type) { - try { - char[] source = getSource(type); - if (source == null) { - return null; - } - return parseHeader(new String(source)); - } catch (Exception e) { - return Utils.printException(e); - } - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JavaCCompiler.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JavaCCompiler.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +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.codegen.processor.compiler; - -import javax.annotation.processing.*; -import javax.lang.model.element.*; - -import com.oracle.truffle.codegen.processor.*; - -public class JavaCCompiler extends AbstractCompiler { - - public static boolean isValidElement(Element currentElement) { - try { - Class elementClass = Class.forName("com.sun.tools.javac.code.Symbol"); - return elementClass.isAssignableFrom(currentElement.getClass()); - } catch (ClassNotFoundException e) { - return false; - } - } - - private static final Class[] getTreeAndTopLevelSignature = new Class[]{Element.class, AnnotationMirror.class, AnnotationValue.class}; - private static final Class[] getCharContentSignature = new Class[]{boolean.class}; - - @Override - public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { - try { - /* - * if (false) { Pair treeAndTopLevel = ((JavacElements) - * env.getElementUtils()).getTreeAndTopLevel(method, null, null); JCBlock block = - * ((JCMethodDecl) treeAndTopLevel.fst).getBody(); int startPos = block.pos; int endPos - * = block.endpos; String methodBody = - * treeAndTopLevel.snd.getSourceFile().getCharContent(true).subSequence(startPos + 1, - * endPos).toString(); return methodBody; } - */ - - Object treeAndTopLevel = getTreeAndTopLevel(env, method); - Object block = method(field(treeAndTopLevel, "fst"), "getBody"); - int startPos = (int) field(block, "pos"); - int endPos = (int) field(block, "endpos"); - return getContent(treeAndTopLevel).subSequence(startPos + 1, endPos).toString(); - } catch (Exception e) { - return Utils.printException(e); - } - } - - private static CharSequence getContent(Object treeAndTopLevel) throws Exception { - /* - * CharSequence content = treeAndTopLevel.snd.getSourceFile().getCharContent(true); - */ - return (CharSequence) method(method(field(treeAndTopLevel, "snd"), "getSourceFile"), "getCharContent", getCharContentSignature, true); - } - - private static Object getTreeAndTopLevel(ProcessingEnvironment env, Element element) throws Exception { - /* - * Pair treeAndTopLevel = ((JavacElements) - * env.getElementUtils()).getTreeAndTopLevel(method, null, null); - */ - return method(method(env, "getElementUtils"), "getTreeAndTopLevel", getTreeAndTopLevelSignature, element, null, null); - } - - @Override - public String getHeaderComment(ProcessingEnvironment env, Element type) { - try { - String content = getContent(getTreeAndTopLevel(env, type)).toString(); - return parseHeader(content); - } catch (Exception e) { - return Utils.printException(e); - } - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/CreateCastData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/CreateCastData.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +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.codegen.processor.node; - -import java.util.*; - -import com.oracle.truffle.codegen.processor.template.*; - -public class CreateCastData extends TemplateMethod { - - private final List childNames; - - public CreateCastData(TemplateMethod method, List childNames) { - super(method); - this.childNames = childNames; - } - - public List getChildNames() { - return childNames; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/CreateCastParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/CreateCastParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +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.codegen.processor.node; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.*; - -public class CreateCastParser extends NodeMethodParser { - - public CreateCastParser(ProcessorContext context, NodeData operation) { - super(context, operation); - } - - @Override - public Class getAnnotationType() { - return CreateCast.class; - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - List childNames = Utils.getAnnotationValueList(String.class, mirror, "value"); - TypeMirror baseType = getContext().getTruffleTypes().getNode(); - for (String childName : childNames) { - NodeChildData child = getNode().findChild(childName); - if (child != null) { - baseType = child.getOriginalType(); - break; - } - } - MethodSpec spec = new MethodSpec(new InheritsParameterSpec(getContext(), "child", baseType)); - addDefaultFieldMethodSpec(method, spec); - spec.addRequired(new ParameterSpec("castedChild", baseType)).setSignature(true); - return spec; - } - - @Override - public CreateCastData create(TemplateMethod method) { - AnnotationMirror mirror = method.getMarkerAnnotation(); - List childNames = Utils.getAnnotationValueList(String.class, mirror, "value"); - CreateCastData cast = new CreateCastData(method, childNames); - AnnotationValue value = Utils.getAnnotationValue(mirror, "value"); - TypeMirror type = null; - if (childNames == null || childNames.isEmpty()) { - cast.addError(value, "No value specified but required."); - return cast; - } - - for (String childName : childNames) { - NodeChildData child = getNode().findChild(childName); - if (child == null) { - // error - cast.addError(value, "Specified child '%s' not found.", childName); - continue; - } - if (type == null) { - type = child.getNodeType(); - } else if (!Utils.typeEquals(type, child.getNodeType())) { - cast.addError(value, "All child nodes for a cast must have the same node type."); - continue; - } - } - return cast; - } - - private static class InheritsParameterSpec extends ParameterSpec { - - private final ProcessorContext context; - - public InheritsParameterSpec(ProcessorContext context, String name, TypeMirror... allowedTypes) { - super(name, Arrays.asList(allowedTypes)); - this.context = context; - } - - @Override - public boolean matches(TypeMirror actualType) { - boolean found = false; - for (TypeMirror specType : getAllowedTypes()) { - if (Utils.isAssignable(context, actualType, specType)) { - found = true; - break; - } - } - return found; - } - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +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.codegen.processor.node; - -import javax.lang.model.element.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.*; -import com.oracle.truffle.codegen.processor.typesystem.*; - -public class ExecutableTypeData extends TemplateMethod { - - private final TypeSystemData typeSystem; - private final TypeData type; - - public ExecutableTypeData(TemplateMethod method, ExecutableElement executable, TypeSystemData typeSystem, TypeData type) { - super(method, executable); - this.typeSystem = typeSystem; - this.type = type; - } - - public TypeData getType() { - return type; - } - - public TypeSystemData getTypeSystem() { - return typeSystem; - } - - public boolean hasFrame() { - return getMethod().getParameters().size() > 0; - } - - public boolean hasUnexpectedValue(ProcessorContext context) { - return Utils.canThrowType(getMethod().getThrownTypes(), context.getTruffleTypes().getUnexpectedValueException()); - } - - public boolean isFinal() { - return getMethod().getModifiers().contains(Modifier.FINAL); - } - - public boolean isAbstract() { - return getMethod().getModifiers().contains(Modifier.ABSTRACT); - } - - public int getEvaluatedCount() { - int count = 0; - for (ActualParameter parameter : getParameters()) { - if (parameter.getSpecification().isSignature()) { - count++; - } - } - return count; - } - - @Override - public int hashCode() { - return type.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof ExecutableTypeData) { - return type.equals(((ExecutableTypeData) obj).type); - } - return super.equals(obj); - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +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.codegen.processor.node; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; -import com.oracle.truffle.codegen.processor.template.*; -import com.oracle.truffle.codegen.processor.typesystem.*; - -public class ExecutableTypeMethodParser extends NodeMethodParser { - - public ExecutableTypeMethodParser(ProcessorContext context, NodeData node) { - super(context, node); - setEmitErrors(false); - setParseNullOnError(false); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null); - List requiredSpecs = new ArrayList<>(spec.getRequired()); - spec.getRequired().clear(); - - for (ParameterSpec originalSpec : requiredSpecs) { - spec.addRequired(new ParameterSpec(originalSpec, Arrays.asList(getNode().getTypeSystem().getGenericType()))); - } - - spec.setVariableRequiredArguments(true); - ParameterSpec other = new ParameterSpec("other", Arrays.asList(getNode().getTypeSystem().getGenericType())); - other.setCardinality(Cardinality.MANY); - other.setSignature(true); - other.setIndexed(true); - spec.addRequired(other); - return spec; - } - - @Override - public final boolean isParsable(ExecutableElement method) { - if (method.getModifiers().contains(Modifier.STATIC)) { - return false; - } else if (method.getModifiers().contains(Modifier.NATIVE)) { - return false; - } - return method.getSimpleName().toString().startsWith("execute"); - } - - @Override - protected List nodeTypeMirrors(NodeData nodeData) { - // executable types not yet available - List types = new ArrayList<>(nodeData.getTypeSystem().getPrimitiveTypeMirrors()); - types.add(nodeData.getTypeSystem().getVoidType().getPrimitiveType()); - return types; - } - - @Override - public ExecutableTypeData create(TemplateMethod method) { - TypeData resolvedType = method.getReturnType().getTypeSystemType(); - return new ExecutableTypeData(method, method.getMethod(), getNode().getTypeSystem(), resolvedType); - } - - @Override - public Class getAnnotationType() { - return null; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +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.codegen.processor.node; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.*; - -public class GenericParser extends NodeMethodParser { - - public GenericParser(ProcessorContext context, NodeData node) { - super(context, node); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return createDefaultMethodSpec(method, mirror, true, null); - } - - @Override - protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, int evaluatedCount) { - List execTypes = nodeData.findGenericExecutableTypes(getContext(), evaluatedCount); - List types = new ArrayList<>(); - for (ExecutableTypeData type : execTypes) { - types.add(type.getType().getPrimitiveType()); - } - ParameterSpec spec = new ParameterSpec(valueName, types); - spec.setSignature(true); - return spec; - } - - @Override - protected ParameterSpec createReturnParameterSpec() { - return super.createValueParameterSpec("returnValue", getNode(), 0); - } - - @Override - public SpecializationData create(TemplateMethod method) { - SpecializationData data = new SpecializationData(method, true, false, false); - return data; - } - - @Override - public Class getAnnotationType() { - return Generic.class; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +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.codegen.processor.node; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.*; -import com.oracle.truffle.codegen.processor.typesystem.*; - -public class NodeChildData extends MessageContainer { - - public enum Cardinality { - ONE, MANY; - - public boolean isMany() { - return this == MANY; - } - - public boolean isOne() { - return this == ONE; - } - } - - public enum ExecutionKind { - DEFAULT, SHORT_CIRCUIT - } - - private final Element sourceElement; - private final AnnotationMirror sourceAnnotationMirror; - - private final String name; - private final TypeMirror type; - private final TypeMirror originalType; - private final Element accessElement; - - private final Cardinality cardinality; - private final ExecutionKind executionKind; - - private List executeWith = Collections.emptyList(); - - private NodeData nodeData; - - public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality, - ExecutionKind executionKind) { - this.sourceElement = sourceElement; - this.sourceAnnotationMirror = sourceMirror; - this.name = name; - this.type = nodeType; - this.originalType = originalNodeType; - this.accessElement = accessElement; - this.cardinality = cardinality; - this.executionKind = executionKind; - } - - public List getExecuteWith() { - return executeWith; - } - - void setExecuteWith(List executeWith) { - this.executeWith = executeWith; - } - - public ExecutableTypeData findExecutableType(ProcessorContext context, TypeData targetType) { - ExecutableTypeData executableType = nodeData.findExecutableType(targetType, getExecuteWith().size()); - if (executableType == null) { - executableType = findAnyGenericExecutableType(context); - } - return executableType; - } - - public List findGenericExecutableTypes(ProcessorContext context) { - return nodeData.findGenericExecutableTypes(context, getExecuteWith().size()); - } - - public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) { - return nodeData.findAnyGenericExecutableType(context, getExecuteWith().size()); - } - - public List findExecutableTypes() { - return nodeData.getExecutableTypes(getExecuteWith().size()); - } - - public TypeMirror getOriginalType() { - return originalType; - } - - @Override - public Element getMessageElement() { - return sourceElement; - } - - @Override - public AnnotationMirror getMessageAnnotation() { - return sourceAnnotationMirror; - } - - public boolean isShortCircuit() { - return executionKind == ExecutionKind.SHORT_CIRCUIT; - } - - void setNode(NodeData nodeData) { - this.nodeData = nodeData; - if (nodeData != null) { - getMessages().addAll(nodeData.collectMessages()); - } - } - - public Element getAccessElement() { - return accessElement; - } - - public TypeMirror getNodeType() { - return type; - } - - public Cardinality getCardinality() { - return cardinality; - } - - public ExecutionKind getExecutionKind() { - return executionKind; - } - - public NodeData getNodeData() { - return nodeData; - } - - public String getName() { - return name; - } - - @Override - public String toString() { - return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", execution=" + executionKind + ", node=" + getNodeData() + "]"; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2438 +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.codegen.processor.node; - -import static com.oracle.truffle.codegen.processor.Utils.*; -import static javax.lang.model.element.Modifier.*; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.api.nodes.NodeInfo.Kind; -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.ast.*; -import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; -import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; -import com.oracle.truffle.codegen.processor.template.*; -import com.oracle.truffle.codegen.processor.typesystem.*; - -public class NodeCodeGenerator extends CompilationUnitFactory { - - private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; - - private static final String EXECUTE_GENERIC_NAME = "executeGeneric0"; - private static final String EXECUTE_SPECIALIZE_NAME = "executeAndSpecialize0"; - - public NodeCodeGenerator(ProcessorContext context) { - super(context); - } - - private TypeMirror getUnexpectedValueException() { - return getContext().getTruffleTypes().getUnexpectedValueException(); - } - - private static String factoryClassName(NodeData node) { - return node.getNodeId() + "Factory"; - } - - private static String nodeSpecializationClassName(SpecializationData specialization) { - String nodeid = specialization.getNode().getNodeId(); - if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { - nodeid = nodeid.substring(0, nodeid.length() - 4); - } - - String name = Utils.firstLetterUpperCase(nodeid); - name += Utils.firstLetterUpperCase(specialization.getId()); - name += "Node"; - return name; - } - - private static String nodePolymorphicClassName(NodeData node, SpecializationData specialization) { - String nodeid = node.getNodeId(); - if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { - nodeid = nodeid.substring(0, nodeid.length() - 4); - } - - String name = Utils.firstLetterUpperCase(nodeid); - int index = specialization == null ? 0 : node.getPolymorphicSpecializations().indexOf(specialization); - if (index == 0) { - name += "PolymorphicNode"; - } else { - name += "Polymorphic" + index + "Node"; - } - return name; - } - - private static String valueNameEvaluated(ActualParameter targetParameter) { - return valueName(targetParameter) + "Evaluated"; - } - - private static String valueName(ActualParameter param) { - return param.getLocalName(); - } - - private static String castValueName(ActualParameter parameter) { - return valueName(parameter) + "Cast"; - } - - 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")); - } - for (ActualParameter parameter : specialization.getParameters()) { - ParameterSpec spec = parameter.getSpecification(); - if (forceFrame && spec.getName().equals("frame")) { - continue; - } - if (spec.isLocal()) { - continue; - } - - String name = valueName(parameter); - if (evaluated && spec.isSignature()) { - name = valueNameEvaluated(parameter); - } - - method.addParameter(new CodeVariableElement(parameter.getType(), name)); - } - } - - private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeImplicit) { - if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { - builder.string("frameValue"); - } - for (ActualParameter parameter : specialization.getParameters()) { - ParameterSpec spec = parameter.getSpecification(); - if (forceFrame && spec.getName().equals("frame")) { - continue; - } - - if (!includeImplicit && (parameter.isImplicit())) { - continue; - } - if (parameter.getSpecification().isLocal()) { - continue; - } - - ActualParameter sourceParameter = source.findParameter(parameter.getLocalName()); - - if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) { - builder.cast(parameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); - } else if (sourceParameter != null) { - builder.string(valueName(sourceParameter, parameter)); - } else { - builder.string(valueName(parameter)); - } - } - } - - private String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) { - if (sourceParameter != null) { - if (!sourceParameter.getSpecification().isSignature()) { - return valueName(targetParameter); - } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) { - if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), targetParameter.getTypeSystemType())) { - return castValueName(targetParameter); - } - } - return valueName(targetParameter); - } else { - return valueName(targetParameter); - } - } - - private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName, - String... customSignatureValueNames) { - CodeTreeBuilder builder = parent.create(); - - boolean castedValues = sourceMethod != targetMethod; - - builder.startGroup(); - ExecutableElement method = targetMethod.getMethod(); - if (method == null) { - throw new UnsupportedOperationException(); - } - TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); - NodeData node = (NodeData) targetMethod.getTemplate(); - - if (target == null) { - boolean accessible = targetMethod.canBeAccessedByInstanceOf(getContext(), node.getNodeType()); - if (accessible) { - if (builder.findMethod().getModifiers().contains(STATIC)) { - if (method.getModifiers().contains(STATIC)) { - builder.type(targetClass.asType()); - } else { - builder.string(THIS_NODE_LOCAL_VAR_NAME); - } - } else { - if (targetMethod instanceof ExecutableTypeData) { - builder.string("this"); - } else { - builder.string("super"); - } - } - } else { - if (method.getModifiers().contains(STATIC)) { - builder.type(targetClass.asType()); - } else { - ActualParameter parameter = null; - for (ActualParameter searchParameter : targetMethod.getParameters()) { - if (searchParameter.getSpecification().isSignature()) { - parameter = searchParameter; - break; - } - } - ActualParameter sourceParameter = sourceMethod.findParameter(parameter.getLocalName()); - assert parameter != null; - - if (castedValues && sourceParameter != null) { - builder.string(valueName(sourceParameter, parameter)); - } else { - builder.string(valueName(parameter)); - } - } - } - builder.string("."); - } else { - builder.tree(target); - } - builder.startCall(method.getSimpleName().toString()); - - int signatureIndex = 0; - - for (ActualParameter targetParameter : targetMethod.getParameters()) { - ActualParameter valueParameter = null; - if (sourceMethod != null) { - valueParameter = sourceMethod.findParameter(targetParameter.getLocalName()); - } - if (valueParameter == null) { - valueParameter = targetParameter; - } - TypeData targetType = targetParameter.getTypeSystemType(); - - if (targetParameter.isImplicit() || valueParameter.isImplicit()) { - continue; - } - - TypeData valueType = null; - if (valueParameter != null) { - valueType = valueParameter.getTypeSystemType(); - } - - if (signatureIndex < customSignatureValueNames.length && targetParameter.getSpecification().isSignature()) { - builder.string(customSignatureValueNames[signatureIndex]); - signatureIndex++; - } else if (targetParameter.getSpecification().isLocal()) { - builder.startGroup(); - if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) { - builder.string(THIS_NODE_LOCAL_VAR_NAME).string("."); - } else { - builder.string("this."); - } - builder.string(targetParameter.getSpecification().getName()); - builder.end(); - } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) { - builder.string("ex.getResult()"); - } else if (targetType == null || targetType.isGeneric() || (valueType != null && valueType.equalsType(targetType))) { - builder.startGroup(); - - if (valueType != null && sourceMethod.getMethodName().equals(targetMethod.getMethodName()) && !valueType.isGeneric() && targetType.isGeneric()) { - builder.string("("); - builder.type(targetType.getPrimitiveType()); - builder.string(") "); - } - builder.string(valueName(targetParameter)); - builder.end(); - } else { - builder.string(castValueName(targetParameter)); - } - } - - builder.end().end(); - - return builder.getRoot(); - } - - private static String baseClassName(NodeData node) { - String nodeid = node.getNodeId(); - if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { - nodeid = nodeid.substring(0, nodeid.length() - 4); - } - String name = Utils.firstLetterUpperCase(nodeid); - name += "BaseNode"; - return name; - } - - private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, CodeTree value) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - startCallTypeSystemMethod(context, builder, node, methodName); - builder.tree(value); - builder.end().end(); - return builder.getRoot(); - } - - private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, NodeData node, String methodName) { - VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, node.getTypeSystem()); - assert singleton != null; - - body.startGroup(); - body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString()); - body.string(".").startCall(methodName); - } - - private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData sourceSpecialization, SpecializationData targetSpecialization, boolean castValues, - CodeTree guardedStatements, CodeTree elseStatements, boolean emitAssumptions, boolean forceElse) { - - NodeData node = targetSpecialization.getNode(); - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, sourceSpecialization, targetSpecialization, emitAssumptions); - CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, sourceSpecialization, targetSpecialization); - - Set valuesNeedsCast; - if (castValues) { - // cast all - valuesNeedsCast = null; - } else { - // find out which values needs a cast - valuesNeedsCast = new HashSet<>(); - for (GuardData guard : targetSpecialization.getGuards()) { - for (ActualParameter targetParameter : guard.getParameters()) { - NodeChildData field = node.findChild(targetParameter.getSpecification().getName()); - if (field == null) { - continue; - } - TypeData targetType = targetParameter.getTypeSystemType(); - ActualParameter sourceParameter = sourceSpecialization.findParameter(targetParameter.getLocalName()); - if (sourceParameter == null) { - sourceParameter = targetParameter; - } - TypeData sourceType = sourceParameter.getTypeSystemType(); - - if (sourceType.needsCastTo(getContext(), targetType)) { - valuesNeedsCast.add(targetParameter.getLocalName()); - } - } - } - } - - int ifCount = 0; - - if (implicitGuards != null) { - builder.startIf(); - builder.tree(implicitGuards); - builder.end(); - builder.startBlock(); - ifCount++; - } - - builder.tree(createCasts(parent, valuesNeedsCast, sourceSpecialization, targetSpecialization)); - - if (explicitGuards != null) { - builder.startIf(); - builder.tree(explicitGuards); - builder.end(); - builder.startBlock(); - ifCount++; - } - - if (implicitGuards == null && explicitGuards == null && conditionPrefix != null && !conditionPrefix.isEmpty()) { - builder.startIf(); - builder.string(conditionPrefix); - builder.end().startBlock(); - ifCount++; - } - - builder.tree(guardedStatements); - - builder.end(ifCount); - if (elseStatements != null && (forceElse || ifCount > 0)) { - builder.tree(elseStatements); - } - return builder.getRoot(); - } - - private CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, TemplateMethod valueSpecialization, SpecializationData guardedSpecialization) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; - if (guardedSpecialization.getGuards().size() > 0) { - // Explicitly specified guards - for (GuardData guard : guardedSpecialization.getGuards()) { - builder.string(andOperator); - builder.tree(createTemplateMethodCall(parent, null, valueSpecialization, guard, null)); - andOperator = " && "; - } - } - - return builder.isEmpty() ? null : builder.getRoot(); - } - - private CodeTree createCasts(CodeTreeBuilder parent, Set castWhiteList, TemplateMethod valueSpecialization, SpecializationData guardedSpecialization) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - // Implict guards based on method signature - for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { - NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName()); - if (field == null) { - continue; - } - ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); - - if (valueParam == null) { - /* - * If used inside a function execute method. The value param may not exist. In that - * case it assumes that the value is already converted. - */ - valueParam = guardedParam; - } - - if (castWhiteList != null && !castWhiteList.contains(guardedParam.getLocalName())) { - continue; - } - - CodeTree cast = createCast(parent, field, valueParam, guardedParam); - if (cast == null) { - continue; - } - builder.tree(cast); - } - - return builder.getRoot(); - } - - private CodeTree createImplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean emitAssumptions) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - // Implict guards based on method signature - String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; - - if (emitAssumptions) { - for (String assumption : guardedSpecialization.getAssumptions()) { - builder.string(andOperator); - builder.string("this"); - builder.string(".").string(assumption).string(".isValid()"); - andOperator = " && "; - } - } - - for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { - NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName()); - if (field == null) { - continue; - } - ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); - - if (valueParam == null) { - /* - * If used inside a function execute method. The value param may not exist. In that - * case it assumes that the value is already converted. - */ - valueParam = guardedParam; - } - - CodeTree implicitGuard = createImplicitGuard(builder, field, valueParam, guardedParam); - if (implicitGuard == null) { - continue; - } - - builder.string(andOperator); - builder.tree(implicitGuard); - andOperator = " && "; - } - - return builder.isEmpty() ? null : builder.getRoot(); - } - - private CodeTree createImplicitGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, ActualParameter target) { - NodeData node = field.getNodeData(); - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - TypeData targetType = target.getTypeSystemType(); - TypeData sourceType = source.getTypeSystemType(); - - if (!sourceType.needsCastTo(getContext(), targetType)) { - return null; - } - - builder.startGroup(); - - if (field.isShortCircuit()) { - ActualParameter shortCircuit = target.getPreviousParameter(); - assert shortCircuit != null; - builder.string("("); - builder.string("!").string(valueName(shortCircuit)); - builder.string(" || "); - } - - startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getTypeSystemType())); - builder.string(valueName(source)); - builder.end().end(); // call - - if (field.isShortCircuit()) { - builder.string(")"); - } - - builder.end(); // group - - return builder.getRoot(); - } - - private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, ActualParameter target) { - NodeData node = field.getNodeData(); - TypeData sourceType = source.getTypeSystemType(); - TypeData targetType = target.getTypeSystemType(); - - if (!sourceType.needsCastTo(getContext(), targetType)) { - return null; - } - - CodeTree condition = null; - if (field.isShortCircuit()) { - ActualParameter shortCircuit = target.getPreviousParameter(); - assert shortCircuit != null; - condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); - } - - CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), CodeTreeBuilder.singleString(valueName(target))); - - return createLazyAssignment(parent, castValueName(target), target.getType(), condition, value); - } - - /** - *

-     * variant1 $condition != null
-     * 
-     * $type $name = defaultValue($type);
-     * if ($condition) {
-     *     $name = $value;
-     * }
-     * 
-     * variant2 $condition != null
-     * $type $name = $value;
-     * 
- * - * . - */ - private static CodeTree createLazyAssignment(CodeTreeBuilder parent, String name, TypeMirror type, CodeTree condition, CodeTree value) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (condition == null) { - builder.declaration(type, name, value); - } else { - builder.declaration(type, name, new CodeTreeBuilder(parent).defaultValue(type).getRoot()); - - builder.startIf().tree(condition).end(); - builder.startBlock(); - builder.startStatement(); - builder.string(name); - builder.string(" = "); - builder.tree(value); - builder.end(); // statement - builder.end(); // block - } - return builder.getRoot(); - } - - protected void emitEncounteredSynthetic(CodeTreeBuilder builder, TemplateMethod current) { - builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)); - builder.startCall("createInfo0"); - builder.doubleQuote("Unsupported values"); - addInternalValueParameterNames(builder, current, current, null, false, true); - builder.end().end().end(); - } - - private static List findUserConstructors(TypeMirror nodeType) { - List constructors = new ArrayList<>(); - for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(nodeType).getEnclosedElements())) { - if (constructor.getModifiers().contains(PRIVATE)) { - continue; - } - if (isCopyConstructor(constructor)) { - continue; - } - constructors.add(constructor); - } - - if (constructors.isEmpty()) { - constructors.add(new CodeExecutableElement(null, Utils.getSimpleName(nodeType))); - } - - return constructors; - } - - private static ExecutableElement findCopyConstructor(TypeMirror type) { - for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(type).getEnclosedElements())) { - if (constructor.getModifiers().contains(PRIVATE)) { - continue; - } - if (isCopyConstructor(constructor)) { - return constructor; - } - } - - return null; - } - - private static boolean isCopyConstructor(ExecutableElement element) { - if (element.getParameters().size() != 1) { - return false; - } - VariableElement var = element.getParameters().get(0); - TypeElement type = Utils.findNearestEnclosingType(var); - - if (!Utils.typeEquals(var.asType(), type.asType())) { - return false; - } - return true; - } - - @Override - protected void createChildren(NodeData node) { - Map> childTypes = new LinkedHashMap<>(); - if (node.getDeclaredNodes() != null && !node.getDeclaredNodes().isEmpty()) { - for (NodeData nodeChild : node.getDeclaredNodes()) { - NodeCodeGenerator generator = new NodeCodeGenerator(getContext()); - childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements()); - } - } - - if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) { - add(new NodeFactoryFactory(context, childTypes), node); - } - } - - private class NodeFactoryFactory extends ClassElementFactory { - - private final Map> childTypes; - - private CodeTypeElement generatedNode; - - public NodeFactoryFactory(ProcessorContext context, Map> childElements) { - super(context); - this.childTypes = childElements; - } - - @Override - protected CodeTypeElement create(NodeData node) { - Modifier visibility = Utils.getVisibility(node.getTemplateType().getModifiers()); - CodeTypeElement clazz = createClass(node, modifiers(), factoryClassName(node), null, false); - if (visibility != null) { - clazz.getModifiers().add(visibility); - } - clazz.getModifiers().add(Modifier.FINAL); - clazz.add(createConstructorUsingFields(modifiers(PRIVATE), clazz)); - return clazz; - } - - @Override - protected void createChildren(NodeData node) { - CodeTypeElement clazz = getElement(); - - Modifier createVisibility = Utils.getVisibility(clazz.getModifiers()); - - if (node.needsFactory()) { - NodeBaseFactory factory = new NodeBaseFactory(context); - add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization()); - generatedNode = factory.getElement(); - - if (node.needsRewrites(context)) { - clazz.add(createCreateGenericMethod(node, createVisibility)); - } - - createFactoryMethods(node, clazz, createVisibility); - - PolymorphicNodeFactory generic = null; - for (SpecializationData specialization : node.getPolymorphicSpecializations()) { - PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(context, generic == null ? generatedNode : generic.getElement(), generic == null); - add(polymorphicFactory, specialization); - if (generic == null) { - generic = polymorphicFactory; - } - } - - for (SpecializationData specialization : node.getSpecializations()) { - if (!specialization.isReachable()) { - continue; - } - add(new SpecializedNodeFactory(context, generatedNode), specialization); - } - - TypeMirror nodeFactory = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType()); - clazz.getImplements().add(nodeFactory); - clazz.add(createCreateNodeMethod(node)); - clazz.add(createCreateNodeGenericMethod(node)); - clazz.add(createGetNodeClassMethod(node)); - clazz.add(createGetNodeSignaturesMethod()); - clazz.add(createGetChildrenSignatureMethod(node)); - clazz.add(createGetInstanceMethod(node, createVisibility)); - clazz.add(createInstanceConstant(node, clazz.asType())); - } - - for (NodeData childNode : childTypes.keySet()) { - if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { - continue; - } - - for (TypeElement type : childTypes.get(childNode)) { - Set typeModifiers = ((CodeTypeElement) type).getModifiers(); - Modifier visibility = Utils.getVisibility(type.getModifiers()); - typeModifiers.clear(); - if (visibility != null) { - typeModifiers.add(visibility); - } - - typeModifiers.add(Modifier.STATIC); - typeModifiers.add(Modifier.FINAL); - clazz.add(type); - } - } - - List children = node.getNodeDeclaringChildren(); - if (node.getParent() == null && children.size() > 0) { - clazz.add(createGetFactories(node)); - } - - } - - private CodeExecutableElement createGetNodeClassMethod(NodeData node) { - TypeMirror returnType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType()); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass"); - CodeTreeBuilder builder = method.createBuilder(); - builder.startReturn().typeLiteral(node.getNodeType()).end(); - return method; - } - - private CodeExecutableElement createGetNodeSignaturesMethod() { - TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class)); - TypeMirror classType = getContext().getType(Class.class); - TypeMirror returnType = Utils.getDeclaredType(listType, Utils.getDeclaredType(listType, classType)); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeSignatures"); - CodeTreeBuilder builder = method.createBuilder(); - builder.startReturn(); - builder.startStaticCall(getContext().getType(Arrays.class), "asList"); - List constructors = findUserConstructors(generatedNode.asType()); - for (ExecutableElement constructor : constructors) { - builder.tree(createAsList(builder, Utils.asTypeMirrors(constructor.getParameters()), classType)); - } - builder.end(); - builder.end(); - return method; - } - - private CodeExecutableElement createGetChildrenSignatureMethod(NodeData node) { - Types types = getContext().getEnvironment().getTypeUtils(); - TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class)); - TypeMirror classType = getContext().getType(Class.class); - TypeMirror nodeType = getContext().getTruffleTypes().getNode(); - TypeMirror wildcardNodeType = types.getWildcardType(nodeType, null); - classType = Utils.getDeclaredType(Utils.fromTypeMirror(classType), wildcardNodeType); - TypeMirror returnType = Utils.getDeclaredType(listType, classType); - - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getExecutionSignature"); - CodeTreeBuilder builder = method.createBuilder(); - - 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); - } - - builder.startReturn().tree(createAsList(builder, signatureTypes, classType)).end(); - return method; - } - - private CodeTree createAsList(CodeTreeBuilder parent, List types, TypeMirror elementClass) { - CodeTreeBuilder builder = parent.create(); - builder.startGroup(); - builder.type(getContext().getType(Arrays.class)); - builder.string(".<").type(elementClass).string(">"); - builder.startCall("asList"); - for (TypeMirror typeMirror : types) { - builder.typeLiteral(typeMirror); - } - builder.end().end(); - return builder.getRoot(); - } - - private CodeExecutableElement createCreateNodeMethod(NodeData node) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode"); - CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments"); - method.setVarArgs(true); - method.addParameter(arguments); - - CodeTreeBuilder builder = method.createBuilder(); - List signatures = findUserConstructors(generatedNode.asType()); - boolean ifStarted = false; - - for (ExecutableElement element : signatures) { - ifStarted = builder.startIf(ifStarted); - builder.string("arguments.length == " + element.getParameters().size()); - - int index = 0; - for (VariableElement param : element.getParameters()) { - builder.string(" && "); - if (!param.asType().getKind().isPrimitive()) { - builder.string("(arguments[" + index + "] == null || "); - } - builder.string("arguments[" + index + "] instanceof "); - builder.type(Utils.boxType(getContext(), param.asType())); - if (!param.asType().getKind().isPrimitive()) { - builder.string(")"); - } - index++; - } - builder.end(); - builder.startBlock(); - - builder.startReturn().startCall("create"); - index = 0; - for (VariableElement param : element.getParameters()) { - builder.startGroup(); - builder.string("(").type(param.asType()).string(") "); - builder.string("arguments[").string(String.valueOf(index)).string("]"); - builder.end(); - index++; - } - builder.end().end(); - - builder.end(); // block - } - - builder.startElseBlock(); - builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)); - builder.doubleQuote("Invalid create signature."); - builder.end().end(); - builder.end(); // else block - return method; - } - - private CodeExecutableElement createCreateNodeGenericMethod(NodeData node) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNodeGeneric"); - CodeVariableElement nodeParam = new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME); - method.addParameter(nodeParam); - - CodeTreeBuilder builder = method.createBuilder(); - if (!node.needsRewrites(getContext())) { - builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).doubleQuote("No specialized version.").end().end(); - } else { - builder.startReturn().startCall("createGeneric"); - builder.string(THIS_NODE_LOCAL_VAR_NAME); - builder.end().end(); - } - return method; - } - - private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) { - TypeElement nodeFactoryType = Utils.fromTypeMirror(getContext().getType(NodeFactory.class)); - TypeMirror returnType = Utils.getDeclaredType(nodeFactoryType, node.getNodeType()); - - CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance"); - if (visibility != null) { - method.getModifiers().add(visibility); - } - method.getModifiers().add(Modifier.STATIC); - - String varName = instanceVarName(node); - - CodeTreeBuilder builder = method.createBuilder(); - builder.startIf(); - builder.string(varName).string(" == null"); - builder.end().startBlock(); - - builder.startStatement(); - builder.string(varName); - builder.string(" = "); - builder.startNew(factoryClassName(node)).end(); - builder.end(); - - builder.end(); - builder.startReturn().string(varName).end(); - return method; - } - - private String instanceVarName(NodeData node) { - if (node.getParent() != null) { - return Utils.firstLetterLowerCase(factoryClassName(node)) + "Instance"; - } else { - return "instance"; - } - } - - private CodeVariableElement createInstanceConstant(NodeData node, TypeMirror factoryType) { - String varName = instanceVarName(node); - CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName); - var.getModifiers().add(Modifier.PRIVATE); - var.getModifiers().add(Modifier.STATIC); - return var; - } - - private ExecutableElement createGetFactories(NodeData node) { - List children = node.getNodeDeclaringChildren(); - if (node.needsFactory()) { - children.add(node); - } - - List nodeTypesList = new ArrayList<>(); - TypeMirror prev = null; - boolean allSame = true; - for (NodeData child : children) { - nodeTypesList.add(child.getNodeType()); - if (prev != null && !Utils.typeEquals(child.getNodeType(), prev)) { - allSame = false; - } - prev = child.getNodeType(); - } - TypeMirror commonNodeSuperType = Utils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()])); - - Types types = getContext().getEnvironment().getTypeUtils(); - TypeMirror factoryType = getContext().getType(NodeFactory.class); - TypeMirror baseType; - if (allSame) { - baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType); - } else { - baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null)); - } - TypeMirror listType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType); - - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories"); - - CodeTreeBuilder builder = method.createBuilder(); - builder.startReturn(); - builder.startStaticCall(getContext().getType(Arrays.class), "asList"); - - for (NodeData child : children) { - builder.startGroup(); - NodeData childNode = child; - List factories = new ArrayList<>(); - while (childNode.getParent() != null) { - factories.add(childNode); - childNode = childNode.getParent(); - } - Collections.reverse(factories); - for (NodeData nodeData : factories) { - builder.string(factoryClassName(nodeData)).string("."); - } - builder.string("getInstance()"); - builder.end(); - } - builder.end(); - builder.end(); - return method; - } - - private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) { - List constructors = findUserConstructors(generatedNode.asType()); - for (ExecutableElement constructor : constructors) { - clazz.add(createCreateMethod(node, createVisibility, constructor)); - } - } - - private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) { - CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), constructor); - method.setSimpleName(CodeNames.of("create")); - method.getModifiers().clear(); - if (visibility != null) { - method.getModifiers().add(visibility); - } - method.getModifiers().add(Modifier.STATIC); - method.setReturnType(node.getNodeType()); - - CodeTreeBuilder body = method.createBuilder(); - body.startReturn(); - if (node.getSpecializations().isEmpty()) { - body.nullLiteral(); - } else { - body.startNew(nodeSpecializationClassName(node.getSpecializations().get(0))); - for (VariableElement var : method.getParameters()) { - body.string(var.getSimpleName().toString()); - } - body.end(); - } - body.end(); - return method; - } - - private CodeExecutableElement createCreateGenericMethod(NodeData node, Modifier visibility) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(), node.getNodeType(), "createGeneric"); - if (visibility != null) { - method.getModifiers().add(visibility); - } - method.getModifiers().add(Modifier.STATIC); - method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); - - CodeTreeBuilder body = method.createBuilder(); - - SpecializationData found = null; - List specializations = node.getSpecializations(); - for (int i = 0; i < specializations.size(); i++) { - if (specializations.get(i).isReachable()) { - found = specializations.get(i); - } - } - - if (found == null) { - body.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end(); - } else { - body.startReturn().startNew(nodeSpecializationClassName(found)).startGroup().cast(baseClassName(node)).string(THIS_NODE_LOCAL_VAR_NAME).end().end().end(); - } - return method; - } - } - - private class NodeBaseFactory extends ClassElementFactory { - - public NodeBaseFactory(ProcessorContext context) { - super(context); - } - - @Override - protected CodeTypeElement create(SpecializationData specialization) { - NodeData node = specialization.getNode(); - CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false); - - for (NodeChildData child : node.getChildren()) { - clazz.add(createChildField(child)); - - if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) { - ExecutableElement getter = (ExecutableElement) child.getAccessElement(); - CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter); - method.getModifiers().remove(Modifier.ABSTRACT); - method.createBuilder().startReturn().string("this.").string(child.getName()).end(); - clazz.add(method); - } - } - - for (String assumption : node.getAssumptions()) { - clazz.add(createAssumptionField(assumption)); - } - - createConstructors(node, clazz); - - return clazz; - } - - protected String typeGetterName(ActualParameter parameter) { - return "get" + Utils.firstLetterUpperCase(parameter.getLocalName()) + "Type"; - } - - @Override - protected void createChildren(SpecializationData specialization) { - NodeData node = specialization.getNode(); - CodeTypeElement clazz = getElement(); - - if (node.needsRewrites(context)) { - - if (node.getPolymorphicDepth() > 1) { - - CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0"); - var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation())); - clazz.add(var); - - CodeExecutableElement setter = new CodeExecutableElement(modifiers(PROTECTED), context.getType(void.class), "setNext0"); - setter.getParameters().add(new CodeVariableElement(clazz.asType(), "next0")); - CodeTreeBuilder builder = setter.createBuilder(); - builder.statement("this.next0 = adoptChild(next0)"); - clazz.add(setter); - - createTypeGetters(clazz, node.getGenericSpecialization()); - - clazz.add(createCreateSpecialization(node)); - - CodeExecutableElement genericCachedExecute = null; - for (SpecializationData polymorph : node.getPolymorphicSpecializations()) { - CodeExecutableElement cachedExecute = createCachedExecute(node, polymorph, genericCachedExecute); - clazz.add(cachedExecute); - if (genericCachedExecute == null) { - genericCachedExecute = cachedExecute; - } - } - } - - clazz.add(createGenericExecuteAndSpecialize(node)); - clazz.add(createInfoMessage(node)); - } - - if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) { - clazz.add(createGenericExecute(node)); - } - } - - private Element createInfoMessage(NodeData node) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), getContext().getType(String.class), "createInfo0"); - method.addParameter(new CodeVariableElement(getContext().getType(String.class), "message")); - addInternalValueParameters(method, node.getGenericSpecialization(), false, false); - - CodeTreeBuilder builder = method.createBuilder(); - builder.startStatement().string("StringBuilder builder = new StringBuilder(message)").end(); - builder.startStatement().startCall("builder", "append").doubleQuote(" (").end().end(); - - String sep = null; - for (ActualParameter parameter : node.getGenericSpecialization().getParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - - builder.startStatement(); - builder.string("builder"); - if (sep != null) { - builder.startCall(".append").doubleQuote(sep).end(); - } - builder.startCall(".append").doubleQuote(parameter.getLocalName()).end(); - builder.startCall(".append").doubleQuote(" = ").end(); - builder.startCall(".append").string(parameter.getLocalName()).end(); - builder.end(); - - if (!Utils.isPrimitive(parameter.getType())) { - builder.startIf().string(parameter.getLocalName() + " != null").end(); - builder.startBlock(); - } - builder.startStatement(); - if (Utils.isPrimitive(parameter.getType())) { - builder.startCall("builder.append").doubleQuote(" (" + Utils.getSimpleName(parameter.getType()) + ")").end(); - } else { - builder.startCall("builder.append").doubleQuote(" (").end(); - builder.startCall(".append").string(parameter.getLocalName() + ".getClass().getSimpleName()").end(); - builder.startCall(".append").doubleQuote(")").end(); - } - builder.end(); - if (!Utils.isPrimitive(parameter.getType())) { - builder.end(); - } - - sep = ", "; - } - - builder.startStatement().startCall("builder", "append").doubleQuote(")").end().end(); - - builder.startReturn().string("builder.toString()").end(); - - return method; - } - - protected void createTypeGetters(CodeTypeElement clazz, SpecializationData specialization) { - for (ActualParameter parameter : specialization.getReturnTypeAndParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - CodeExecutableElement typeGetter = new CodeExecutableElement(modifiers(PROTECTED), context.getType(Class.class), typeGetterName(parameter)); - CodeTreeBuilder builder = typeGetter.createBuilder(); - builder.startReturn().typeLiteral(parameter.getType()).end(); - clazz.add(typeGetter); - } - } - - private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph, CodeExecutableElement genericPolymorphMethod) { - int index = node.getPolymorphicSpecializations().indexOf(polymorph); - assert index != -1; - boolean generic = index == 0; - - String name = "executeCached" + index; - CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED), polymorph.getReturnType().getType(), name); - addInternalValueParameters(cachedExecute, polymorph, true, true); - - if (generic) { - cachedExecute.getModifiers().add(ABSTRACT); - } else { - SpecializationData genericPolymorph = node.getPolymorphicSpecializations().get(0); - CodeTreeBuilder builder = cachedExecute.createBuilder(); - ExecutableTypeData genericExecutable = new ExecutableTypeData(genericPolymorph, genericPolymorphMethod, node.getTypeSystem(), genericPolymorph.getReturnType().getTypeSystemType()); - ExecutableTypeData specificExecutable = new ExecutableTypeData(polymorph, cachedExecute, node.getTypeSystem(), polymorph.getReturnType().getTypeSystemType()); - builder.tree(createCastingExecute(builder, polymorph, specificExecutable, genericExecutable)); - } - - return cachedExecute; - - } - - private CodeExecutableElement createCreateSpecialization(NodeData node) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), getElement().asType(), "createSpezialization0"); - method.getParameters().add(new CodeVariableElement(context.getType(Class.class), "clazz")); - CodeTreeBuilder builder = method.createBuilder(); - - builder.startStatement().type(getElement().asType()).string(" node").end(); - - boolean elseIf = false; - for (SpecializationData specialization : node.getSpecializations()) { - if (specialization.isGeneric() || specialization.isUninitialized()) { - continue; - } - - elseIf = builder.startIf(elseIf); - builder.startGroup().string("clazz == ").string(nodeSpecializationClassName(specialization)).string(".class").end(); - builder.end(); - builder.startBlock(); - builder.startStatement(); - builder.string("node = "); - builder.startNew(nodeSpecializationClassName(specialization)).string("this").end(); - builder.end(); - builder.end(); - } - - builder.startElseBlock(); - builder.startThrow().startNew(context.getType(AssertionError.class)).end().end(); - builder.end(); - - builder.startStatement().startCall("node", "setNext0"); - builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end(); - builder.end().end(); - - builder.startReturn().string("node").end(); - - return method; - } - - private void createConstructors(NodeData node, CodeTypeElement clazz) { - List constructors = findUserConstructors(node.getNodeType()); - if (constructors.isEmpty()) { - clazz.add(createUserConstructor(clazz, null)); - } else { - for (ExecutableElement constructor : constructors) { - clazz.add(createUserConstructor(clazz, constructor)); - } - } - if (node.needsRewrites(getContext())) { - clazz.add(createCopyConstructor(clazz, findCopyConstructor(node.getNodeType()))); - } - } - - private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) { - CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); - CodeTreeBuilder builder = method.createBuilder(); - - NodeData node = getModel().getNode(); - - if (superConstructor != null) { - for (VariableElement param : superConstructor.getParameters()) { - method.getParameters().add(CodeVariableElement.clone(param)); - } - } - - 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()) { - builder.string(param.getSimpleName().toString()); - } - builder.end().end(); - } - - for (VariableElement var : type.getFields()) { - builder.startStatement(); - String fieldName = var.getSimpleName().toString(); - - CodeTree fieldInit = CodeTreeBuilder.singleString(var.getSimpleName().toString()); - builder.string("this.").string(var.getSimpleName().toString()); - - NodeChildData child = node.findChild(fieldName); - if (child != null) { - CreateCastData createCast = node.findCast(child.getName()); - if (createCast != null) { - fieldInit = createTemplateMethodCall(builder, null, node.getGenericSpecialization(), createCast, null, child.getName()); - } - } - - if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) { - builder.string(" = adoptChild(").tree(fieldInit).string(")"); - } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) { - builder.string(" = adoptChildren(").tree(fieldInit).string(")"); - } else { - builder.string(" = ").tree(fieldInit); - } - builder.end(); - } - return method; - } - - private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor) { - CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); - CodeTreeBuilder builder = method.createBuilder(); - if (!(superConstructor == null && type.getFields().isEmpty())) { - method.getParameters().add(new CodeVariableElement(type.asType(), "copy")); - } - - if (superConstructor != null) { - builder.startStatement().startSuperCall().string("copy").end().end(); - } - - for (VariableElement var : type.getFields()) { - builder.startStatement(); - String varName = var.getSimpleName().toString(); - builder.string("this.").string(varName); - if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) { - builder.string(" = adoptChild(copy.").string(varName).string(")"); - } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) { - builder.string(" = adoptChildren(copy.").string(varName).string(")"); - } else { - builder.string(" = copy.").string(varName); - } - builder.end(); - } - if (getModel().getNode().getPolymorphicDepth() > 1) { - builder.statement("this.next0 = adoptChild(copy.next0)"); - } - - return method; - } - - private CodeVariableElement createAssumptionField(String assumption) { - CodeVariableElement var = new CodeVariableElement(getContext().getTruffleTypes().getAssumption(), assumption); - var.getModifiers().add(Modifier.FINAL); - return var; - } - - private CodeVariableElement createChildField(NodeChildData child) { - CodeVariableElement var = new CodeVariableElement(child.getNodeType(), child.getName()); - var.getModifiers().add(Modifier.PROTECTED); - - DeclaredType annotationType; - if (child.getCardinality() == Cardinality.MANY) { - annotationType = getContext().getTruffleTypes().getChildrenAnnotation(); - } else { - annotationType = getContext().getTruffleTypes().getChildAnnotation(); - } - - var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType)); - return var; - } - - private CodeExecutableElement createGenericExecuteAndSpecialize(NodeData node) { - - TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_SPECIALIZE_NAME); - method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); - addInternalValueParameters(method, node.getGenericSpecialization(), true, false); - method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason")); - - CodeTreeBuilder builder = method.createBuilder(); - builder.startStatement(); - builder.startStaticCall(getContext().getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end(); - builder.end(); - - emitSpecializationListeners(builder, node); - builder.defaultDeclaration(node.getGenericSpecialization().getReturnType().getTypeSystemType().getPrimitiveType(), "result"); - - builder.defaultDeclaration(getContext().getType(Class.class), "resultClass"); - - builder.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end(); - - builder.startStatement().string("String message = ").startCall("createInfo0").string("reason"); - addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, true); - builder.end().end(); - - String prefix = null; - - List specializations = node.getSpecializations(); - - for (SpecializationData current : specializations) { - if (current.isUninitialized() || !current.isReachable()) { - continue; - } - CodeTreeBuilder execute = new CodeTreeBuilder(builder); - - execute.tree(createGenericInvokeAndSpecialize(builder, node.getGenericSpecialization(), current)); - - if (!current.isGeneric()) { - builder.startStatement().string("allowed = allowed || (minimumState == ").string(nodeSpecializationClassName(current)).string(".class)").end(); - } - - builder.tree(createGuardAndCast(builder, prefix, current.getNode().getGenericSpecialization(), current, true, execute.getRoot(), null, true, false)); - } - - for (SpecializationData current : specializations) { - if (current.isUninitialized() || current.isReachable()) { - continue; - } - builder.string("// unreachable ").string(current.getId()).newLine(); - } - - return method; - } - - private CodeExecutableElement createGenericExecute(NodeData node) { - TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_GENERIC_NAME); - addInternalValueParameters(method, node.getGenericSpecialization(), true, false); - CodeTreeBuilder builder = method.createBuilder(); - - String prefix = null; - List specializations = node.getSpecializations(); - - for (SpecializationData current : specializations) { - if (current.isUninitialized() || !current.isReachable()) { - continue; - } - CodeTreeBuilder execute = new CodeTreeBuilder(builder); - execute.tree(createGenericInvoke(builder, node.getGenericSpecialization(), current)); - builder.tree(createGuardAndCast(builder, prefix, current.getNode().getGenericSpecialization(), current, true, execute.getRoot(), null, true, false)); - } - - for (SpecializationData current : specializations) { - if (current.isUninitialized() || current.isReachable()) { - continue; - } - builder.string("// unreachable ").string(current.getId()).newLine(); - } - - return method; - } - - protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - if (current.getMethod() == null) { - emitEncounteredSynthetic(builder, current); - } else { - builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end(); - } - - return encloseThrowsWithFallThrough(current, builder.getRoot()); - } - - protected CodeTree createGenericInvokeAndSpecialize(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - NodeData node = current.getNode(); - - builder.startIf().string("resultClass == null").end().startBlock(); - if (current.getMethod() != null) { - CodeTree executeCall = createTemplateMethodCall(builder, null, source, current, null); - if (current.getReturnType().getTypeSystemType().isVoid()) { - builder.statement(executeCall); - } else { - builder.startStatement().string("result = ").tree(executeCall).end(); - } - builder.startStatement(); - builder.string("resultClass = ").string(nodeSpecializationClassName(current)).string(".class"); - builder.end(); - } else { - emitEncounteredSynthetic(builder, current); - } - builder.end(); - - boolean ifAllowed = current.hasRewrite(getContext()); - if (ifAllowed) { - builder.startIf().string("allowed").end().startBlock(); - } - - if (!current.isGeneric() || node.getPolymorphicDepth() <= 1) { - // generic rewrite - builder.tree(createRewriteGeneric(builder, current)); - } else { - boolean rewriteableToGeneric = node.getGenericSpecialization().getMethod() != null && node.getGenericSpecialization().isReachable(); - if (rewriteableToGeneric) { - builder.startIf().string("resultClass == ").string(nodeSpecializationClassName(node.getGenericSpecialization())).string(".class").end(); - builder.startBlock(); - - boolean maybePolymorphic = node.getPolymorphicDepth() > 1; - if (maybePolymorphic) { - builder.startIf().string("next0 == null").end(); - builder.startBlock(); - } - builder.tree(createRewriteGeneric(builder, current)); - if (maybePolymorphic) { - builder.end().startElseBlock(); - builder.statement("Node searchNode = super.getParent()"); - builder.startWhile().string("searchNode != null").end(); - builder.startBlock(); - builder.statement("searchNode = searchNode.getParent()"); - builder.startIf().instanceOf("searchNode", nodePolymorphicClassName(node, node.getPolymorphicSpecializations().get(0))).end(); - builder.startBlock().breakStatement().end(); - builder.end(); - builder.startStatement().startCall("searchNode", "replace"); - builder.startGroup().startNew(nodeSpecializationClassName(current)).startGroup().cast(baseClassName(node)).string("searchNode").end().end().end(); - builder.string("message"); - builder.end().end().end(); - } - - builder.end().startElseBlock(); - } - - // polymorphic rewrite - builder.tree(createRewritePolymorphic(builder, node)); - - if (rewriteableToGeneric) { - builder.end(); - } - } - - if (current.getReturnType().getTypeSystemType().isVoid()) { - builder.returnStatement(); - } else { - builder.startReturn().string("result").end(); - } - if (ifAllowed) { - builder.end(); - } - - return encloseThrowsWithFallThrough(current, builder.getRoot()); - } - - private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree) { - if (current.getExceptions().isEmpty()) { - return tree; - } - CodeTreeBuilder builder = new CodeTreeBuilder(null); - - builder.startTryBlock(); - builder.tree(tree); - for (SpecializationThrowsData exception : current.getExceptions()) { - builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx"); - builder.string("// fall through").newLine(); - } - builder.end(); - - return builder.getRoot(); - } - - private CodeTree createRewriteGeneric(CodeTreeBuilder parent, SpecializationData current) { - CodeTreeBuilder builder = parent.create(); - builder.startStatement().startCall("super", "replace"); - builder.startGroup().startNew(nodeSpecializationClassName(current)).string("this").end().end(); - builder.string("message"); - builder.end().end(); - return builder.getRoot(); - } - - private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node) { - CodeTreeBuilder builder = parent.create(); - builder.startStatement(); - builder.string(nodePolymorphicClassName(node, null)); - builder.string(" polymorphic = "); - builder.startNew(nodePolymorphicClassName(node, null)).string("this").end(); - builder.end(); - for (NodeChildData child : node.getChildren()) { - builder.startStatement().string("this.").string(child.getName()).string(" = null").end(); - } - builder.startStatement().startCall("super", "replace"); - builder.string("polymorphic"); - builder.string("message"); - builder.end().end(); - - builder.statement("polymorphic.setNext0(this)"); - builder.statement("setNext0(createSpezialization0(resultClass))"); - - builder.statement("polymorphic.optimizeTypes()"); - 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); - NodeData node = specialization.getNode(); - - ExecutableTypeData castedType = node.findExecutableType(type, 0); - TypeData primaryType = castExecutable.getType(); - - boolean needsTry = castExecutable.hasUnexpectedValue(getContext()); - boolean returnVoid = type.isVoid(); - - List executeParameters = new ArrayList<>(); - for (ActualParameter sourceParameter : executable.getParameters()) { - if (!sourceParameter.getSpecification().isSignature()) { - continue; - } - - ActualParameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName()); - if (targetParameter != null) { - executeParameters.add(targetParameter); - } - } - - builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null, true)); - - CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null); - if (needsTry) { - if (!returnVoid) { - builder.declaration(primaryType.getPrimitiveType(), "value"); - } - builder.startTryBlock(); - - if (returnVoid) { - builder.statement(primaryExecuteCall); - } else { - builder.startStatement(); - builder.string("value = "); - builder.tree(primaryExecuteCall); - builder.end(); - } - - builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); - if (returnVoid) { - builder.string("// ignore").newLine(); - } else { - builder.startReturn(); - builder.tree(createExpectExecutableType(node, specialization.getNode().getTypeSystem().getGenericTypeData(), castedType, CodeTreeBuilder.singleString("ex.getResult()"))); - builder.end(); - } - builder.end(); - - if (!returnVoid) { - builder.startReturn(); - builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, CodeTreeBuilder.singleString("value"))); - builder.end(); - } - } else { - if (returnVoid) { - builder.statement(primaryExecuteCall); - } else { - builder.startReturn(); - builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, primaryExecuteCall)); - builder.end(); - } - } - - return builder.getRoot(); - } - - protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, ExecutableTypeData castedType, CodeTree value) { - boolean hasUnexpected = castedType.hasUnexpectedValue(getContext()); - return createCastType(node, sourceType, castedType.getType(), hasUnexpected, value); - } - - protected CodeTree createCastType(NodeData node, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) { - if (targetType == null) { - return value; - } else if (!sourceType.needsCastTo(getContext(), targetType)) { - return value; - } - - CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - String targetMethodName; - if (expect) { - targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType); - } else { - targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); - } - startCallTypeSystemMethod(getContext(), builder, node, targetMethodName); - - builder.tree(value); - builder.end().end(); - return builder.getRoot(); - } - - protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List targetParameters, - ActualParameter unexpectedParameter, boolean cast) { - NodeData sourceNode = specialization.getNode(); - - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - for (ActualParameter targetParameter : targetParameters) { - NodeChildData field = sourceNode.findChild(targetParameter.getSpecification().getName()); - if (!targetParameter.getSpecification().isSignature()) { - continue; - } - - TypeData targetType = targetParameter.getTypeSystemType(); - ExecutableTypeData targetExecutable = null; - if (field != null) { - targetExecutable = field.findExecutableType(getContext(), targetType); - } - - ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); - - String targetVariableName = valueName(targetParameter); - CodeTree executionExpression = null; - if ((sourceParameter != null && cast) || sourceParameter != null) { - TypeData sourceType = sourceParameter.getTypeSystemType(); - if (targetExecutable == null || !sourceType.needsCastTo(getContext(), targetType)) { - if (field != null && field.isShortCircuit() && sourceParameter != null) { - builder.tree(createShortCircuitValue(builder, specialization, field, targetParameter.getPreviousParameter(), unexpectedParameter)); - } - builder.startStatement(); - builder.type(targetParameter.getType()).string(" "); - builder.string(valueName(targetParameter)).string(" = "); - builder.tree(CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter))); - builder.end(); - continue; - } else { - CodeTree valueTree = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)); - executionExpression = createExpectExecutableType(sourceNode, sourceType, targetExecutable, valueTree); - } - } else if (sourceParameter == null) { - executionExpression = createExecuteChildExpression(builder, field, targetParameter, unexpectedParameter); - } - - if (executionExpression != null) { - CodeTreeVariable executionVar = new CodeTreeVariable(); - CodeTree shortCircuitTree = createShortCircuitTree(builder, executionVar, targetVariableName, specialization, targetParameter, unexpectedParameter); - CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpression, targetVariableName, specialization, sourceExecutable, targetExecutable, targetParameter, - shortCircuitTree != executionVar); - - executionVar.set(unexpectedTree); - builder.tree(shortCircuitTree); - } - } - return builder.getRoot(); - } - - private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ExecutableTypeData currentExecutable, - ExecutableTypeData targetExecutable, ActualParameter param, boolean shortCircuit) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - boolean unexpected = targetExecutable.hasUnexpectedValue(getContext()); - boolean cast = false; - if (targetExecutable.getType().needsCastTo(getContext(), param.getTypeSystemType())) { - unexpected = true; - cast = true; - } - - if (specialization.isGeneric() && unexpected) { - throw new AssertionError("Generic has unexpected parameters. " + specialization.toString()); - } - - builder.startStatement(); - - if (!shortCircuit) { - builder.type(param.getType()).string(" ").string(targetVariableName); - } - - if (unexpected) { - if (!shortCircuit) { - builder.end(); - } - builder.startTryBlock(); - builder.startStatement(); - builder.string(targetVariableName); - } else if (shortCircuit) { - builder.startStatement(); - builder.string(targetVariableName); - } - builder.string(" = "); - if (cast) { - builder.tree(createCastType(specialization.getNode(), targetExecutable.getType(), param.getTypeSystemType(), true, body)); - } else { - builder.tree(body); - } - builder.end(); - - if (unexpected) { - builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); - SpecializationData generic = specialization.getNode().getGenericSpecialization(); - ActualParameter genericParameter = generic.findParameter(param.getLocalName()); - - List genericParameters = generic.getParametersAfter(genericParameter); - builder.tree(createDeoptimize(builder)); - builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false)); - if (specialization.isPolymorphic()) { - builder.tree(createReturnOptimizeTypes(builder, specialization, param)); - } else { - builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization.findNextSpecialization(), param, "Expected " + param.getLocalName() + " instanceof " + - Utils.getSimpleName(param.getType()))); - } - builder.end(); // catch block - } - - return builder.getRoot(); - } - - private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, SpecializationData specialization, ActualParameter param) { - NodeData node = specialization.getNode(); - assert !node.getPolymorphicSpecializations().isEmpty(); - SpecializationData generic = node.getPolymorphicSpecializations().get(0); - - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - builder.startReturn(); - - CodeTreeBuilder execute = new CodeTreeBuilder(builder); - execute.startCall("next0", "executeCached0"); - addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true); - execute.end(); - - TypeData sourceType = generic.getReturnType().getTypeSystemType(); - TypeData targetType = specialization.getReturnType().getTypeSystemType(); - - builder.tree(createCastType(node, sourceType, targetType, true, execute.getRoot())); - - builder.end(); - return builder.getRoot(); - } - - private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetField, ActualParameter sourceParameter, ActualParameter unexpectedParameter) { - TypeData type = sourceParameter.getTypeSystemType(); - ExecutableTypeData execType = targetField.findExecutableType(getContext(), type); - - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (targetField != null) { - Element accessElement = targetField.getAccessElement(); - if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) { - builder.string("this.").string(targetField.getName()); - } else if (accessElement.getKind() == ElementKind.FIELD) { - builder.string("this.").string(accessElement.getSimpleName().toString()); - } else { - throw new AssertionError(); - } - if (sourceParameter.getSpecification().isIndexed()) { - builder.string("[" + sourceParameter.getIndex() + "]"); - } - builder.string("."); - } - - builder.startCall(execType.getMethodName()); - - int index = 0; - for (ActualParameter parameter : execType.getParameters()) { - - if (!parameter.getSpecification().isSignature()) { - builder.string(parameter.getLocalName()); - } else { - if (index < targetField.getExecuteWith().size()) { - NodeChildData child = targetField.getExecuteWith().get(index); - - ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName()); - List specializationParams = getModel().findParameters(spec); - - if (specializationParams.isEmpty()) { - builder.defaultValue(parameter.getType()); - continue; - } - - ActualParameter specializationParam = specializationParams.get(0); - - TypeData targetType = parameter.getTypeSystemType(); - TypeData sourceType = specializationParam.getTypeSystemType(); - String localName = specializationParam.getLocalName(); - - if (unexpectedParameter != null && unexpectedParameter.getLocalName().equals(specializationParam.getLocalName())) { - localName = "ex.getResult()"; - sourceType = getModel().getNode().getTypeSystem().getGenericTypeData(); - } - - CodeTree value = CodeTreeBuilder.singleString(localName); - - if (sourceType.needsCastTo(getContext(), targetType)) { - value = createCallTypeSystemMethod(getContext(), builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value); - } - builder.tree(value); - } else { - builder.defaultValue(parameter.getType()); - } - index++; - } - } - - builder.end(); - - return builder.getRoot(); - } - - private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ActualParameter parameter, - ActualParameter exceptionParam) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName()); - if (forField == null) { - return body; - } - - if (forField.getExecutionKind() != ExecutionKind.SHORT_CIRCUIT) { - return body; - } - - ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter); - - builder.tree(createShortCircuitValue(builder, specialization, forField, shortCircuitParam, exceptionParam)); - - builder.declaration(parameter.getType(), targetVariableName, CodeTreeBuilder.createBuilder().defaultValue(parameter.getType())); - builder.startIf().string(shortCircuitParam.getLocalName()).end(); - builder.startBlock(); - builder.tree(body); - builder.end(); - - return builder.getRoot(); - } - - private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeChildData forField, 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) { - break; - } - shortCircuitIndex++; - } - } - - builder.startStatement().type(shortCircuitParam.getType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); - ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex); - builder.tree(createTemplateMethodCall(builder, null, specialization, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); - builder.end(); // statement - - return builder.getRoot(); - } - - protected CodeTree createDeoptimize(CodeTreeBuilder parent) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - builder.startStatement(); - builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end(); - builder.end(); - return builder.getRoot(); - } - - protected CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData nextSpecialization, ActualParameter exceptionParam, String reason) { - SpecializationData generic = getModel().getNode().getGenericSpecialization(); - CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); - specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); - specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class"); - addInternalValueParameterNames(specializeCall, generic, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true); - specializeCall.doubleQuote(reason); - specializeCall.end().end(); - - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - builder.startReturn(); - builder.tree(createExpectExecutableType(nextSpecialization.getNode(), generic.getReturnType().getTypeSystemType(), executable, specializeCall.getRoot())); - builder.end(); - - return builder.getRoot(); - } - } - - private class PolymorphicNodeFactory extends SpecializedNodeFactory { - - private final boolean generic; - - public PolymorphicNodeFactory(ProcessorContext context, CodeTypeElement nodeGen, boolean generic) { - super(context, nodeGen); - this.generic = generic; - } - - @Override - public CodeTypeElement create(SpecializationData specialization) { - NodeData node = specialization.getNode(); - TypeMirror baseType = node.getNodeType(); - if (nodeGen != null) { - baseType = nodeGen.asType(); - } - CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC), nodePolymorphicClassName(node, specialization), baseType, false); - - if (!generic) { - clazz.getModifiers().add(Modifier.FINAL); - } - - clazz.getAnnotationMirrors().add(createNodeInfo(node, Kind.POLYMORPHIC)); - - return clazz; - } - - @Override - protected void createChildren(SpecializationData specialization) { -// super.createChildren(specialization); - CodeTypeElement clazz = getElement(); - - createConstructors(clazz); - createExecuteMethods(specialization); - - if (generic) { - getElement().add(createOptimizeTypes()); - createCachedExecuteMethods(specialization); - } - } - - private CodeExecutableElement createOptimizeTypes() { - NodeData node = getModel().getNode(); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), getContext().getType(void.class), "optimizeTypes"); - CodeTreeBuilder builder = method.createBuilder(); - builder.startStatement().string(baseClassName(node)).string(" node = this.next0").end(); - TypeMirror classType = getContext().getType(Class.class); - - SpecializationData genericSpecialization = node.getGenericSpecialization(); - - CodeTreeBuilder whileBodyBuilder = builder.create(); - for (ActualParameter parameter : node.getGenericSpecialization().getReturnTypeAndParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - - ActualParameter genericParameter = genericSpecialization.findParameter(parameter.getLocalName()); - - String name = parameter.getLocalName() + "Type"; - - builder.declaration(classType, name, builder.create().startCall("node", typeGetterName(parameter)).end().getRoot()); - - whileBodyBuilder.startIf().string(name).string(" != ").startCall("node", typeGetterName(parameter)).end().end(); - whileBodyBuilder.startBlock(); - whileBodyBuilder.startStatement().string(name).string(" = ").typeLiteral(genericParameter.getType()).end(); - whileBodyBuilder.end(); - } - - builder.startWhile().string("node != null && !(").instanceOf("node", nodeSpecializationClassName(node.getUninitializedSpecialization())).string(")").end(); - builder.startBlock(); - builder.tree(whileBodyBuilder.getRoot()); - builder.statement("node = node.next0"); - builder.end(); - - boolean elseIf = false; - for (SpecializationData polymorph : node.getPolymorphicSpecializations()) { - elseIf = builder.startIf(elseIf); - String and = ""; - StringBuilder reason = new StringBuilder("Optimized polymorphic types for ("); - for (ActualParameter parameter : polymorph.getReturnTypeAndParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - String name = parameter.getLocalName() + "Type"; - builder.string(and).string(name).string(" == ").typeLiteral(parameter.getType()); - - if (!and.isEmpty()) { - reason.append(", "); - } - reason.append(Utils.getSimpleName(parameter.getType())); - and = " && "; - } - reason.append(")"); - builder.end(); - builder.startBlock(); - - String className = nodePolymorphicClassName(node, polymorph); - builder.startIf().string("getClass() != ").string(className).string(".class").end(); - builder.startBlock(); - builder.startStatement().startCall("super", "replace"); - builder.startNew(className).string("this").end(); - builder.doubleQuote(reason.toString()); - builder.end().end(); // call - builder.end(); // block - builder.end(); - } - return method; - } - } - - private class SpecializedNodeFactory extends NodeBaseFactory { - - protected final CodeTypeElement nodeGen; - - public SpecializedNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) { - super(context); - this.nodeGen = nodeGen; - } - - @Override - public CodeTypeElement create(SpecializationData specialization) { - NodeData node = specialization.getNode(); - TypeMirror baseType = node.getNodeType(); - if (nodeGen != null) { - baseType = nodeGen.asType(); - } - CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false); - - Kind kind; - if (specialization.isGeneric()) { - kind = Kind.GENERIC; - } else if (specialization.isUninitialized()) { - kind = Kind.UNINITIALIZED; - } else { - kind = Kind.SPECIALIZED; - } - clazz.getAnnotationMirrors().add(createNodeInfo(node, kind)); - - return clazz; - } - - protected CodeAnnotationMirror createNodeInfo(NodeData node, Kind kind) { - String shortName = node.getShortName(); - CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation()); - if (shortName != null) { - nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName)); - } - - DeclaredType nodeinfoKind = getContext().getTruffleTypes().getNodeInfoKind(); - VariableElement varKind = Utils.findVariableElement(nodeinfoKind, kind.name()); - - nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("kind"), new CodeAnnotationValue(varKind)); - return nodeInfoMirror; - } - - @Override - protected void createChildren(SpecializationData specialization) { - CodeTypeElement clazz = getElement(); - createConstructors(clazz); - - NodeData node = specialization.getNode(); - - if (!specialization.isGeneric() && !specialization.isUninitialized() && !specialization.isPolymorphic() && node.needsRewrites(getContext()) && node.getPolymorphicDepth() > 1) { - - createTypeGetters(clazz, specialization); - } - - createExecuteMethods(specialization); - createCachedExecuteMethods(specialization); - } - - protected void createConstructors(CodeTypeElement clazz) { - TypeElement superTypeElement = Utils.fromTypeMirror(clazz.getSuperclass()); - for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) { - if (getModel().getNode().getUninitializedSpecialization() != null && !getModel().isUninitialized() && constructor.getParameters().size() != 1 || - constructor.getParameters().get(0).getSimpleName().toString().equals(baseClassName(getModel().getNode()))) { - continue; - } - - CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor); - if (superConstructor != null) { - if (getModel().isGeneric() && getModel().getNode().getPolymorphicDepth() > 1) { - CodeTree body = superConstructor.getBodyTree(); - CodeTreeBuilder builder = superConstructor.createBuilder(); - builder.tree(body); - builder.statement("this.next0 = null"); - } - - clazz.add(superConstructor); - } - } - } - - protected void createExecuteMethods(SpecializationData specialization) { - NodeData node = specialization.getNode(); - CodeTypeElement clazz = getElement(); - - for (ExecutableTypeData execType : node.getExecutableTypes()) { - if (execType.isFinal()) { - continue; - } - CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, true); - clazz.add(executeMethod); - CodeTreeBuilder builder = executeMethod.createBuilder(); - CodeTree result = createExecuteBody(builder, specialization, execType); - if (result != null) { - builder.tree(result); - } else { - clazz.remove(executeMethod); - } - } - } - - protected void createCachedExecuteMethods(SpecializationData specialization) { - NodeData node = specialization.getNode(); - CodeTypeElement clazz = getElement(); - int index = 0; - for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) { - boolean matchFound = false; - if (!specialization.isGeneric() && !specialization.isUninitialized() && !specialization.isPolymorphic()) { - matchFound = polymorphic.getSignature().hasAnyParameterMatch(specialization.getSignature()); - } - - if (matchFound || index == 0) { - ExecutableElement executeCached = nodeGen.getMethod("executeCached" + index); - ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached, node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType()); - - CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, false); - CodeTreeBuilder builder = executeMethod.createBuilder(); - - if (specialization.isGeneric() || specialization.isPolymorphic()) { - builder.startThrow().startNew(getContext().getType(AssertionError.class)); - builder.doubleQuote("Should not be reached."); - builder.end().end(); - } else if (specialization.isUninitialized()) { - builder.tree(createAppendPolymorphic(builder, specialization)); - } else { - CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); - elseBuilder.startReturn().startCall("this.next0", "executeCached" + index); - addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true); - elseBuilder.end().end(); - CodeTreeBuilder execute = new CodeTreeBuilder(builder); - execute.tree(createGenericInvoke(builder, polymorphic, specialization)); - boolean forceElse = !specialization.getExceptions().isEmpty(); - builder.tree(createGuardAndCast(builder, null, polymorphic, specialization, true, execute.getRoot(), elseBuilder.getRoot(), true, forceElse)); - } - clazz.add(executeMethod); - } - index++; - } - } - - private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) { - NodeData node = specialization.getNode(); - String genericClassName = nodePolymorphicClassName(node, null); - - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end(); - - builder.declaration(getContext().getTruffleTypes().getNode(), "searchNode", "super.getParent()"); - builder.declaration(getContext().getType(int.class), "depth", "0"); - builder.startWhile().string("searchNode != null").end(); - builder.startBlock(); - builder.statement("depth++"); - builder.statement("searchNode = searchNode.getParent()"); - - builder.startIf().instanceOf("searchNode", genericClassName).end(); - builder.startBlock().breakStatement().end(); - builder.end(); // if - builder.end(); // while - - builder.startAssert().instanceOf("searchNode", genericClassName).end(); - - builder.startStatement(); - builder.string(genericClassName).string(" ").string("polymorphic = ").string("(").string(genericClassName).string(") searchNode"); - builder.end(); - - builder.startIf().string("depth >= ").string(String.valueOf(node.getPolymorphicDepth())).end(); - builder.startBlock(); - builder.startStatement(); - builder.startCall("searchNode", "replace"); - builder.startNew(nodeSpecializationClassName(node.getGenericSpecialization())).string("this").end(); - builder.doubleQuote("Polymorphic limit reached (" + node.getPolymorphicDepth() + ")"); - builder.end(); - builder.end(); - - builder.startReturn().startCall("super", EXECUTE_GENERIC_NAME); - addInternalValueParameterNames(builder, specialization, node.getGenericSpecialization(), null, true, true); - builder.end().end(); - - builder.end().startElseBlock(); - builder.startStatement().startCall("super", "setNext0"); - builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end(); - builder.end().end(); - - CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder); - specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); - specializeCall.string(nodeSpecializationClassName(node.getUninitializedSpecialization()) + ".class"); - addInternalValueParameterNames(specializeCall, specialization, node.getGenericSpecialization(), null, true, true); - specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end(); - specializeCall.end().end(); - - builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot()); - - builder.statement("polymorphic.optimizeTypes()"); - - if (Utils.isVoid(builder.findMethod().getReturnType())) { - builder.returnStatement(); - } else { - builder.startReturn().string("result").end(); - } - - builder.end(); - - return builder.getRoot(); - } - - private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) { - TypeData primaryType = specialization.getReturnType().getTypeSystemType(); - - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - List primaryExecutes = findFunctionalExecutableType(specialization, execType.getEvaluatedCount()); - - if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) { - builder.tree(createFunctionalExecute(builder, specialization, execType)); - } else if (needsCastingExecuteMethod(execType, primaryType)) { - assert !primaryExecutes.isEmpty(); - builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0))); - } else { - return null; - } - - return builder.getRoot(); - } - - private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) { - CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); - - int i = 0; - for (VariableElement param : method.getParameters()) { - CodeVariableElement var = CodeVariableElement.clone(param); - ActualParameter actualParameter = execType.getParameters().get(i); - if (evaluated && actualParameter.getSpecification().isSignature()) { - var.setName(valueNameEvaluated(actualParameter)); - } else { - var.setName(valueName(actualParameter)); - } - method.getParameters().set(i, var); - i++; - } - - method.getAnnotationMirrors().clear(); - method.getModifiers().remove(Modifier.ABSTRACT); - return method; - } - - private boolean needsCastingExecuteMethod(ExecutableTypeData execType, TypeData primaryType) { - if (execType.isAbstract()) { - return true; - } - if (Utils.isPrimitiveOrVoid(primaryType.getPrimitiveType()) && Utils.isPrimitiveOrVoid(execType.getType().getPrimitiveType())) { - return true; - } - if (execType.getType().isGeneric()) { - return true; - } - return false; - } - - private List findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) { - TypeData primaryType = specialization.getReturnType().getTypeSystemType(); - List otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount); - - List filteredTypes = new ArrayList<>(); - for (ExecutableTypeData compareType : otherTypes) { - if (!Utils.typeEquals(compareType.getType().getPrimitiveType(), primaryType.getPrimitiveType())) { - continue; - } - filteredTypes.add(compareType); - } - - // no direct matches found use generic where the type is Object - if (filteredTypes.isEmpty()) { - for (ExecutableTypeData compareType : otherTypes) { - if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(getContext())) { - filteredTypes.add(compareType); - } - } - } - - if (filteredTypes.isEmpty()) { - for (ExecutableTypeData compareType : otherTypes) { - if (compareType.getType().isGeneric()) { - filteredTypes.add(compareType); - } - } - } - - return filteredTypes; - } - - private CodeTree createFunctionalExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (specialization.isUninitialized()) { - builder.tree(createDeoptimize(builder)); - } - - builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null, false)); - - CodeTree executeNode = createExecute(builder, executable, specialization); - - SpecializationData next = specialization.findNextSpecialization(); - CodeTree returnSpecialized = null; - if (next != null) { - CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder); - returnBuilder.tree(createDeoptimize(builder)); - returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, next, null, "One of guards " + specialization.getGuards() + " failed")); - returnSpecialized = returnBuilder.getRoot(); - } - builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized, false, false)); - - return builder.getRoot(); - } - - private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { - NodeData node = specialization.getNode(); - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (!specialization.getExceptions().isEmpty() || !specialization.getAssumptions().isEmpty()) { - builder.startTryBlock(); - } - - for (String assumption : specialization.getAssumptions()) { - builder.startStatement(); - builder.string("this.").string(assumption).string(".check()"); - builder.end(); - } - - CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); - if (specialization.isPolymorphic()) { - int index = 0; - if (executable.hasUnexpectedValue(getContext())) { - index = specialization.getNode().getPolymorphicSpecializations().indexOf(specialization); - } - returnBuilder.startCall("next0", "executeCached" + index); - addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true); - returnBuilder.end(); - } else if (specialization.isUninitialized()) { - returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME); - returnBuilder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end(); - addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true); - returnBuilder.doubleQuote("Uninitialized monomorphic"); - returnBuilder.end(); - } else if (specialization.getMethod() == null && !node.needsRewrites(context)) { - emitEncounteredSynthetic(builder, specialization); - } else if (specialization.isGeneric()) { - returnBuilder.startCall("super", EXECUTE_GENERIC_NAME); - addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true); - returnBuilder.end(); - } else { - returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null)); - } - - if (!returnBuilder.isEmpty()) { - builder.startReturn(); - - TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType()); - TypeData sourceType = specialization.getReturnType().getTypeSystemType(); - - if (targetType == null || sourceType == null) { - builder.tree(returnBuilder.getRoot()); - } else if (sourceType.needsCastTo(getContext(), targetType)) { - builder.tree(createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.expectTypeMethodName(targetType), returnBuilder.getRoot())); - } else { - builder.tree(returnBuilder.getRoot()); - } - builder.end(); - } - - if (!specialization.getExceptions().isEmpty()) { - for (SpecializationThrowsData exception : specialization.getExceptions()) { - builder.end().startCatchBlock(exception.getJavaClass(), "ex"); - builder.tree(createDeoptimize(builder)); - builder.tree(createReturnExecuteAndSpecialize(parent, executable, exception.getTransitionTo(), null, "Thrown " + Utils.getSimpleName(exception.getJavaClass()))); - } - builder.end(); - } - if (!specialization.getAssumptions().isEmpty()) { - builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex"); - builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization.findNextSpecialization(), null, "Assumption failed")); - builder.end(); - } - - return builder.getRoot(); - } - - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,552 +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.codegen.processor.node; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; -import com.oracle.truffle.codegen.processor.template.*; -import com.oracle.truffle.codegen.processor.typesystem.*; - -public class NodeData extends Template { - - private final String nodeId; - private NodeData declaringNode; - private List declaredNodes = new ArrayList<>(); - private boolean nodeContainer; - - private TypeSystemData typeSystem; - private List children; - private List fields; - private TypeMirror nodeType; - private ParameterSpec instanceParameterSpec; - - private List specializations; - private List polymorphicSpecializations; - private List specializationListeners; - 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) { - super(type, null, null); - this.nodeId = id; - } - - public NodeData(NodeData splitSource, String templateMethodName, String nodeId) { - super(splitSource.getTemplateType(), templateMethodName, null); - this.nodeId = nodeId; - this.declaringNode = splitSource.declaringNode; - this.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 int getPolymorphicDepth() { - return polymorphicDepth; - } - - void setPolymorphicDepth(int polymorphicDepth) { - this.polymorphicDepth = polymorphicDepth; - } - - public List getCasts() { - 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 (typeSystem != null) { - containerChildren.add(typeSystem); - } - if (specializations != null) { - for (MessageContainer specialization : specializations) { - if (specialization.getMessageElement() != null) { - containerChildren.add(specialization); - } - } - } - if (specializationListeners != null) { - containerChildren.addAll(specializationListeners); - } - if (executableTypes != null) { - containerChildren.addAll(getExecutableTypes()); - } - if (shortCircuits != null) { - containerChildren.addAll(shortCircuits); - } - if (children != null) { - containerChildren.addAll(children); - } - if (fields != null) { - containerChildren.addAll(fields); - } - if (casts != null) { - containerChildren.addAll(casts); - } - return containerChildren; - } - - public ParameterSpec getInstanceParameterSpec() { - return instanceParameterSpec; - } - - public void setInstanceParameterSpec(ParameterSpec instanceParameter) { - this.instanceParameterSpec = instanceParameter; - } - - public String getNodeId() { - return nodeId; - } - - public TypeMirror getNodeType() { - if (nodeType != null) { - return nodeType; - } - return getTemplateType().asType(); - } - - void setAssumptions(List assumptions) { - this.assumptions = assumptions; - } - - public List getAssumptions() { - return assumptions; - } - - public boolean needsFactory() { - if (specializations == null) { - return false; - } - if (getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { - return false; - } - - boolean noSpecialization = true; - for (SpecializationData specialization : specializations) { - noSpecialization = noSpecialization && specialization.isGeneric() || specialization.isUninitialized(); - } - return !noSpecialization; - } - - public boolean supportsFrame() { - if (executableTypes != null) { - for (ExecutableTypeData execType : getExecutableTypes(-1)) { - if (execType.findParameter("frameValue") == null) { - return false; - } - } - } - return true; - } - - public List getNodeDeclaringChildren() { - List nodeChildren = new ArrayList<>(); - for (NodeData child : getDeclaredNodes()) { - if (child.needsFactory()) { - nodeChildren.add(child); - } - nodeChildren.addAll(child.getNodeDeclaringChildren()); - } - return nodeChildren; - } - - void setDeclaredNodes(List declaredChildren) { - this.declaredNodes = declaredChildren; - - for (NodeData child : declaredChildren) { - child.declaringNode = this; - } - } - - public NodeData getParent() { - return declaringNode; - } - - public List getDeclaredNodes() { - return declaredNodes; - } - - public void setNodeType(TypeMirror nodeType) { - this.nodeType = nodeType; - } - - public List getAllTemplateMethods() { - List methods = new ArrayList<>(); - - for (SpecializationData specialization : getSpecializations()) { - methods.add(specialization); - } - - methods.addAll(getSpecializationListeners()); - methods.addAll(getExecutableTypes()); - methods.addAll(getShortCircuits()); - if (getCasts() != null) { - methods.addAll(getCasts()); - } - - return methods; - } - - public ExecutableTypeData findGenericExecutableType(ProcessorContext context, TypeData type, int evaluatedCount) { - List types = findGenericExecutableTypes(context, evaluatedCount); - for (ExecutableTypeData availableType : types) { - if (Utils.typeEquals(availableType.getType().getBoxedType(), type.getBoxedType())) { - return availableType; - } - } - return null; - } - - public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context, int evaluatedCount) { - List types = findGenericExecutableTypes(context, evaluatedCount); - for (ExecutableTypeData type : types) { - if (type.getType().isGeneric()) { - return type; - } - } - - for (ExecutableTypeData type : types) { - if (!type.getType().isVoid()) { - return type; - } - } - - for (ExecutableTypeData type : types) { - return type; - } - return null; - } - - public List getExecutableTypes(int evaluatedCount) { - if (executableTypes == null) { - return Collections.emptyList(); - } - if (evaluatedCount == -1) { - List typeData = new ArrayList<>(); - for (int currentEvaluationCount : executableTypes.keySet()) { - typeData.addAll(executableTypes.get(currentEvaluationCount)); - } - return typeData; - } else { - List types = executableTypes.get(evaluatedCount); - if (types == null) { - return Collections.emptyList(); - } - return types; - } - } - - public List findGenericExecutableTypes(ProcessorContext context, int evaluatedCount) { - List types = new ArrayList<>(); - for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) { - if (!type.hasUnexpectedValue(context)) { - types.add(type); - } - } - return types; - } - - public ExecutableTypeData findExecutableType(TypeData prmitiveType, int evaluatedCount) { - for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) { - if (Utils.typeEquals(type.getType().getPrimitiveType(), prmitiveType.getPrimitiveType())) { - return type; - } - } - return null; - } - - public SpecializationData findUniqueSpecialization(TypeData type) { - SpecializationData result = null; - for (SpecializationData specialization : specializations) { - if (specialization.getReturnType().getTypeSystemType() == type) { - if (result != null) { - // Result not unique; - return null; - } - result = specialization; - } - } - 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; - - for (SpecializationData specialization : getSpecializations()) { - if (specialization.hasRewrite(context)) { - needsRewrites = true; - break; - } - } - return needsRewrites || getSpecializations().size() > 1; - } - - public SpecializationData getGenericSpecialization() { - for (SpecializationData specialization : specializations) { - if (specialization.isGeneric()) { - return specialization; - } - } - return null; - } - - public SpecializationData getUninitializedSpecialization() { - for (SpecializationData specialization : specializations) { - if (specialization.isUninitialized()) { - return specialization; - } - } - return null; - } - - @Override - public TypeSystemData getTypeSystem() { - return typeSystem; - } - - public String dump() { - return dump(0); - } - - private String dump(int level) { - String indent = ""; - for (int i = 0; i < level; i++) { - indent += " "; - } - StringBuilder builder = new StringBuilder(); - - builder.append(String.format("%s%s {", indent, toString())); - - dumpProperty(builder, indent, "templateClass", Utils.getQualifiedName(getTemplateType())); - dumpProperty(builder, indent, "typeSystem", getTypeSystem()); - dumpProperty(builder, indent, "fields", getChildren()); - 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) { - builder.append(String.format("\n%s children = [", indent)); - for (NodeData node : getDeclaredNodes()) { - builder.append("\n"); - builder.append(node.dump(level + 1)); - } - builder.append(String.format("\n%s ]", indent)); - } - builder.append(String.format("%s}", indent)); - return builder.toString(); - } - - private static void dumpProperty(StringBuilder b, String indent, String propertyName, Object value) { - if (value instanceof List) { - List list = (List) value; - if (!list.isEmpty()) { - b.append(String.format("\n%s %s = %s", indent, propertyName, dumpList(indent, (List) value))); - } - } else { - if (value != null) { - b.append(String.format("\n%s %s = %s", indent, propertyName, value)); - } - } - } - - private static String dumpList(String indent, List array) { - if (array == null) { - return "null"; - } - - if (array.isEmpty()) { - return "[]"; - } else if (array.size() == 1) { - return "[" + array.get(0).toString() + "]"; - } - - StringBuilder b = new StringBuilder(); - b.append("["); - for (Object object : array) { - b.append("\n "); - b.append(indent); - b.append(object); - b.append(", "); - } - b.append("\n ").append(indent).append("]"); - return b.toString(); - } - - public NodeChildData findChild(String name) { - for (NodeChildData field : getChildren()) { - if (field.getName().equals(name)) { - return field; - } - } - return null; - } - - public List getChildren() { - 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; - } - - public List getExecutableTypes() { - return getExecutableTypes(-1); - } - - public List getShortCircuits() { - 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 setSpecializationListeners(List specializationListeners) { - this.specializationListeners = specializationListeners; - } - - void setExecutableTypes(Map> executableTypes) { - this.executableTypes = executableTypes; - } - - void setShortCircuits(List shortCircuits) { - this.shortCircuits = shortCircuits; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "[" + getNodeId() + "]"; - } - - public CreateCastData findCast(String name) { - if (getCasts() != null) { - for (CreateCastData cast : getCasts()) { - if (cast.getChildNames().contains(name)) { - return cast; - } - } - } - return null; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +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.codegen.processor.node; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.template.*; - -public class NodeFieldData extends MessageContainer { - - private VariableElement variable; - - public NodeFieldData(VariableElement var) { - this.variable = var; - } - - @Override - public Element getMessageElement() { - return variable; - } - - public String getName() { - return variable.getSimpleName().toString(); - } - - public TypeMirror getType() { - return variable.asType(); - } - - public VariableElement getVariable() { - return variable; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +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.codegen.processor.node; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; -import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; -import com.oracle.truffle.codegen.processor.template.*; - -public abstract class NodeMethodParser extends TemplateMethodParser { - - public NodeMethodParser(ProcessorContext context, NodeData node) { - super(context, node); - } - - public NodeData getNode() { - return template; - } - - @SuppressWarnings("unused") - protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, int evaluatedCount) { - ParameterSpec spec = new ParameterSpec(valueName, nodeTypeMirrors(nodeData)); - spec.setSignature(true); - return spec; - } - - protected List nodeTypeMirrors(NodeData nodeData) { - Set typeMirrors = new LinkedHashSet<>(); - - for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) { - typeMirrors.add(typeData.getType().getPrimitiveType()); - } - - typeMirrors.add(nodeData.getTypeSystem().getGenericType()); - - return new ArrayList<>(typeMirrors); - } - - protected ParameterSpec createReturnParameterSpec() { - return createValueParameterSpec("returnValue", getNode(), 0); - } - - @Override - public boolean isParsable(ExecutableElement method) { - if (getAnnotationType() != null) { - return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; - } - - return true; - } - - @SuppressWarnings("unused") - protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, boolean shortCircuitsEnabled, String shortCircuitName) { - MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec()); - - addDefaultFrame(methodSpec); - addDefaultImplicitThis(method, methodSpec); - addDefaultFieldMethodSpec(method, methodSpec); - addDefaultChildren(shortCircuitsEnabled, shortCircuitName, methodSpec); - - return methodSpec; - } - - private void addDefaultChildren(boolean shortCircuitsEnabled, String shortCircuitName, MethodSpec methodSpec) { - // children are null when parsing executable types - if (getNode().getChildren() != null) { - for (NodeChildData child : getNode().getChildren()) { - if (child.getExecutionKind() == ExecutionKind.DEFAULT) { - ParameterSpec spec = createValueParameterSpec(child.getName(), child.getNodeData(), child.getExecuteWith().size()); - if (child.getCardinality().isMany()) { - spec.setCardinality(Cardinality.MANY); - spec.setIndexed(true); - } - methodSpec.addRequired(spec); - } else if (child.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) { - String valueName = child.getName(); - if (shortCircuitName != null && valueName.equals(shortCircuitName)) { - break; - } - - if (shortCircuitsEnabled) { - methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class))); - } - methodSpec.addRequired(createValueParameterSpec(valueName, child.getNodeData(), child.getExecuteWith().size())); - } else { - assert false; - } - } - } - } - - private void addDefaultFrame(MethodSpec methodSpec) { - if (getNode().supportsFrame()) { - methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame())); - } - } - - protected void addDefaultFieldMethodSpec(ExecutableElement method, MethodSpec methodSpec) { - for (NodeFieldData field : getNode().getFields()) { - if (!Utils.isFieldAccessible(method, field.getVariable())) { - ParameterSpec spec = new ParameterSpec(field.getName(), field.getType()); - spec.setLocal(true); - methodSpec.addOptional(spec); - } - } - } - - protected void addDefaultImplicitThis(ExecutableElement method, MethodSpec methodSpec) { - TypeMirror declaredType = Utils.findNearestEnclosingType(method).asType(); - - if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(getContext(), declaredType, getContext().getTruffleTypes().getNode())) { - methodSpec.addImplicitRequiredType(getNode().getTemplateType().asType()); - } - } - - private static String shortCircuitValueName(String valueName) { - return "has" + Utils.firstLetterUpperCase(valueName); - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1190 +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.codegen.processor.node; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; -import javax.tools.Diagnostic.Kind; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; -import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; -import com.oracle.truffle.codegen.processor.template.*; -import com.oracle.truffle.codegen.processor.template.TemplateMethod.Signature; -import com.oracle.truffle.codegen.processor.typesystem.*; - -public class NodeParser extends TemplateParser { - - 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); - - private Map parsedNodes; - - public NodeParser(ProcessorContext c) { - super(c); - } - - @Override - protected NodeData parse(Element element, AnnotationMirror mirror) { - assert element instanceof TypeElement; - NodeData node = null; - try { - parsedNodes = new HashMap<>(); - node = resolveNode((TypeElement) element); - if (Log.DEBUG) { - NodeData parsed = parsedNodes.get(Utils.getQualifiedName((TypeElement) element)); - if (node != null) { - String dump = parsed.dump(); - log.message(Kind.ERROR, null, null, null, dump); - } - } - } finally { - parsedNodes = null; - } - - return node; - } - - @Override - protected NodeData filterErrorElements(NodeData model) { - for (Iterator iterator = model.getDeclaredNodes().iterator(); iterator.hasNext();) { - NodeData node = filterErrorElements(iterator.next()); - if (node == null) { - iterator.remove(); - } - } - if (model.hasErrors()) { - return null; - } - return model; - } - - @Override - public boolean isDelegateToRootDeclaredType() { - return true; - } - - @Override - public Class getAnnotationType() { - return null; - } - - @Override - public List> getTypeDelegatedAnnotationTypes() { - return ANNOTATIONS; - } - - private NodeData resolveNode(TypeElement rootType) { - String typeName = Utils.getQualifiedName(rootType); - if (parsedNodes.containsKey(typeName)) { - 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); - } - } - - NodeData rootNode = parseNode(rootType); - if (rootNode == null && children.size() > 0) { - rootNode = new NodeData(rootType, rootType.getSimpleName().toString()); - } - - parsedNodes.put(typeName, rootNode); - - if (rootNode != null) { - children.addAll(rootNode.getDeclaredNodes()); - rootNode.setDeclaredNodes(children); - } - - return rootNode; - } - - private NodeData parseNode(TypeElement originalTemplateType) { - // reloading the type elements is needed for ecj - TypeElement templateType = Utils.fromTypeMirror(context.reloadTypeElement(originalTemplateType)); - - if (Utils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) { - // generated nodes should not get called again. - 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) { - 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); - - Set types = new HashSet<>(); - for (ListIterator iterator = lookupTypes.listIterator(); iterator.hasNext();) { - TypeElement typeElement = iterator.next(); - if (types.contains(typeElement)) { - iterator.remove(); - } else { - types.add(typeElement); - } - } - } - List elements = new ArrayList<>(elementSet); - - NodeData node = parseNodeData(templateType, nodeType, elements, lookupTypes); - - if (node.hasErrors()) { - return node; // error sync point - } - - parseMethods(node, elements); - - if (node.hasErrors()) { - return node; - } - - List nodes; - - if (node.isNodeContainer()) { - nodes = splitNodeData(node); - } else { - nodes = new ArrayList<>(); - nodes.add(node); - } - - for (NodeData splittedNode : nodes) { - finalizeSpecializations(elements, splittedNode); - verifyNode(splittedNode, elements); - splittedNode.setPolymorphicSpecializations(createPolymorphicSpecializations(splittedNode)); - assignShortCircuitsToSpecializations(splittedNode); - } - - if (node.isNodeContainer()) { - node.setDeclaredNodes(nodes); - node.setSpecializationListeners(new ArrayList()); - node.setSpecializations(new ArrayList()); - } - return node; - } - - private List createPolymorphicSpecializations(NodeData node) { - if (!node.needsRewrites(context) || node.getPolymorphicDepth() <= 1) { - return Collections.emptyList(); - } - - Signature genericSignature = node.getGenericSpecialization().getSignature(); - Set signatures = new HashSet<>(); - - for (SpecializationData specialization1 : node.getSpecializations()) { - Signature signature = specialization1.getSignature(); - - for (SpecializationData specialization2 : node.getSpecializations()) { - if (specialization1 == specialization2) { - continue; - } - signatures.add(signature.combine(genericSignature, specialization2.getSignature())); - } - } - - while (true) { - List newSignatures = new ArrayList<>(); - for (Signature signature1 : signatures) { - for (Signature signature2 : signatures) { - if (signature1 == signature2) { - continue; - } - newSignatures.add(signature1.combine(genericSignature, signature2)); - } - } - if (!signatures.addAll(newSignatures)) { - break; - } - } - - List sortedSignatures = new ArrayList<>(signatures); - Collections.sort(sortedSignatures); - - List specializations = new ArrayList<>(); - SpecializationData generic = node.getGenericSpecialization(); - for (Signature signature : sortedSignatures) { - SpecializationData specialization = new SpecializationData(generic, false, false, true); - specialization.forceFrame(context.getTruffleTypes().getFrame()); - specialization.setNode(node); - specialization.updateSignature(signature); - - if (specialization.isGenericSpecialization(context)) { - specializations.add(0, specialization); - } else { - specializations.add(specialization); - } - } - - return specializations; - } - - private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List elements, List lookupTypes) { - NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString()); - - AnnotationMirror typeSystemMirror = findFirstAnnotation(lookupTypes, TypeSystemReference.class); - if (typeSystemMirror == null) { - nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(nodeType)); - return nodeData; - } - - TypeMirror typeSytemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value"); - final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true); - if (typeSystem == null) { - nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSytemType)); - return nodeData; - } - - AnnotationMirror polymorphicMirror = findFirstAnnotation(lookupTypes, PolymorphicLimit.class); - if (polymorphicMirror != null) { - AnnotationValue limitValue = Utils.getAnnotationValue(polymorphicMirror, "value"); - int polymorphicLimit = Utils.getAnnotationValue(Integer.class, polymorphicMirror, "value"); - if (polymorphicLimit < 1) { - nodeData.addError(limitValue, "Invalid polymorphic limit %s.", polymorphicLimit); - } - nodeData.setPolymorphicDepth(polymorphicLimit); - } - - List assumptionsList = new ArrayList<>(); - for (int i = lookupTypes.size() - 1; i >= 0; i--) { - TypeElement type = lookupTypes.get(i); - AnnotationMirror assumptions = Utils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class); - if (assumptions != null) { - List assumptionStrings = Utils.getAnnotationValueList(String.class, assumptions, "value"); - for (String string : assumptionStrings) { - if (assumptionsList.contains(string)) { - assumptionsList.remove(string); - } - assumptionsList.add(string); - } - } - } - AnnotationMirror nodeInfoMirror = findFirstAnnotation(lookupTypes, NodeInfo.class); - if (nodeInfoMirror != null) { - nodeData.setShortName(Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName")); - } - - nodeData.setAssumptions(new ArrayList<>(assumptionsList)); - nodeData.setNodeType(nodeType); - AnnotationMirror nodeContainer = findFirstAnnotation(lookupTypes, NodeContainer.class); - nodeData.setNodeContainer(nodeContainer != null); - nodeData.setTypeSystem(typeSystem); - nodeData.setFields(parseFields(elements)); - parsedNodes.put(Utils.getQualifiedName(templateType), nodeData); - // parseChildren invokes cyclic parsing. - nodeData.setChildren(parseChildren(elements, lookupTypes)); - nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements))); - - return nodeData; - } - - private static List parseFields(List elements) { - List fields = new ArrayList<>(); - for (VariableElement field : ElementFilter.fieldsIn(elements)) { - if (field.getModifiers().contains(Modifier.STATIC)) { - continue; - } - if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) { - fields.add(new NodeFieldData(field)); - } - } - return fields; - } - - private List parseChildren(List elements, final List typeHierarchy) { - Set shortCircuits = new HashSet<>(); - for (ExecutableElement method : ElementFilter.methodsIn(elements)) { - AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class); - if (mirror != null) { - shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value")); - } - } - Map castNodeTypes = new HashMap<>(); - for (ExecutableElement method : ElementFilter.methodsIn(elements)) { - AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, CreateCast.class); - if (mirror != null) { - List children = (Utils.getAnnotationValueList(String.class, mirror, "value")); - if (children != null) { - for (String child : children) { - castNodeTypes.put(child, method.getReturnType()); - } - } - } - } - - List parsedChildren = new ArrayList<>(); - 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(); - if (!Utils.isAssignable(context, nodeClassType, context.getTruffleTypes().getNode())) { - 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) { - String name = Utils.getAnnotationValue(String.class, childMirror, "value"); - if (name.equals("")) { - name = "child" + index; - } - - Cardinality cardinality = Cardinality.ONE; - - TypeMirror childType = inheritType(childMirror, "type", nodeClassType); - if (childType.getKind() == TypeKind.ARRAY) { - cardinality = Cardinality.MANY; - } - - TypeMirror originalChildType = childType; - TypeMirror castNodeType = castNodeTypes.get(name); - if (castNodeType != null) { - childType = castNodeType; - } - - Element getter = findGetter(elements, name, childType); - - ExecutionKind kind = ExecutionKind.DEFAULT; - if (shortCircuits.contains(name)) { - kind = ExecutionKind.SHORT_CIRCUIT; - } - - NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality, kind); - - parsedChildren.add(nodeChild); - - verifyNodeChild(nodeChild); - if (nodeChild.hasErrors()) { - continue; - } - - NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(childType)); - nodeChild.setNode(fieldNodeData); - if (fieldNodeData == null) { - nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(childType)); - } - - } - index++; - } - - List filteredChildren = new ArrayList<>(); - Set encounteredNames = new HashSet<>(); - for (int i = parsedChildren.size() - 1; i >= 0; i--) { - NodeChildData child = parsedChildren.get(i); - if (!encounteredNames.contains(child.getName())) { - filteredChildren.add(0, child); - encounteredNames.add(child.getName()); - } - } - - for (NodeChildData child : filteredChildren) { - List executeWithStrings = Utils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith"); - AnnotationValue executeWithValue = Utils.getAnnotationValue(child.getMessageAnnotation(), "executeWith"); - List executeWith = new ArrayList<>(); - for (String executeWithString : executeWithStrings) { - - if (child.getName().equals(executeWithString)) { - child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString); - continue; - } - - NodeChildData found = null; - boolean before = true; - for (NodeChildData resolveChild : filteredChildren) { - if (resolveChild == child) { - before = false; - continue; - } - if (resolveChild.getName().equals(executeWithString)) { - found = resolveChild; - break; - } - } - - if (found == null) { - child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString); - continue; - } else if (!before) { - child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString, - executeWithString); - continue; - } - executeWith.add(found); - } - child.setExecuteWith(executeWith); - if (child.getNodeData() == null) { - continue; - } - - List types = child.findGenericExecutableTypes(context); - if (types.isEmpty()) { - child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", executeWith.size(), Utils.getSimpleName(child.getNodeType())); - continue; - } - } - - 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)); - - List allSpecializations = new ArrayList<>(); - allSpecializations.addAll(generics); - allSpecializations.addAll(specializations); - - node.setSpecializations(allSpecializations); - } - - 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()); - - 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<>(); - } - - 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); - } - - node.setSpecializations(new ArrayList()); - node.setSpecializationListeners(new ArrayList()); - node.setCasts(new ArrayList()); - - return splitted; - } - - private void finalizeSpecializations(List elements, final NodeData node) { - List specializations = new ArrayList<>(node.getSpecializations()); - - if (specializations.isEmpty()) { - return; - } - - for (SpecializationData specialization : specializations) { - matchGuards(elements, specialization); - } - - List generics = new ArrayList<>(); - for (SpecializationData spec : specializations) { - if (spec.isGeneric()) { - generics.add(spec); - } - } - - 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)) { - SpecializationData specialization = specializations.get(0); - GenericParser parser = new GenericParser(context, node); - MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null); - - ExecutableTypeData anyGenericReturnType = node.findAnyGenericExecutableType(context, 0); - assert anyGenericReturnType != null; - - ActualParameter returnType = new ActualParameter(specification.getReturnType(), anyGenericReturnType.getType(), 0, false); - List parameters = new ArrayList<>(); - for (ActualParameter specializationParameter : specialization.getParameters()) { - ParameterSpec parameterSpec = specification.findParameterSpec(specializationParameter.getSpecification().getName()); - NodeChildData child = node.findChild(parameterSpec.getName()); - TypeData actualType; - if (child == null) { - actualType = specializationParameter.getTypeSystemType(); - } else { - ExecutableTypeData paramType = child.findAnyGenericExecutableType(context); - assert paramType != null; - actualType = paramType.getType(); - } - - if (actualType != null) { - parameters.add(new ActualParameter(parameterSpec, actualType, specializationParameter.getIndex(), specializationParameter.isImplicit())); - } else { - parameters.add(new ActualParameter(parameterSpec, specializationParameter.getType(), specializationParameter.getIndex(), specializationParameter.isImplicit())); - } - } - TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters); - genericSpecialization = new SpecializationData(genericMethod, true, false, false); - - specializations.add(genericSpecialization); - } - - 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)); - } - - Collections.sort(specializations); - - node.setSpecializations(specializations); - - List needsId = new ArrayList<>(); - for (SpecializationData specialization : specializations) { - if (specialization.isGeneric()) { - specialization.setId("Generic"); - } else if (specialization.isUninitialized()) { - specialization.setId("Uninitialized"); - } else { - needsId.add(specialization); - } - } - - // 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)); - } - } - - // calculate reachability - int specializationCount = 0; - boolean reachable = true; - for (SpecializationData specialization : specializations) { - if (specialization.isUninitialized()) { - specialization.setReachable(true); - continue; - } - if (!reachable && specialization.getMethod() != null) { - specialization.addError("%s is not reachable.", specialization.isGeneric() ? "Generic" : "Specialization"); - } - specialization.setReachable(reachable); - if (!specialization.hasRewrite(context)) { - reachable = false; - } - if (!specialization.isGeneric()) { - specializationCount++; - } - } - - if (node.getPolymorphicDepth() < 0) { - node.setPolymorphicDepth(specializationCount - 1); - } - - // reduce polymorphicness if generic is not reachable - if (node.getGenericSpecialization() != null && !node.getGenericSpecialization().isReachable()) { - node.setPolymorphicDepth(1); - } - } - - 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) { - int lastSize = -1; - List> signatureChunks = new ArrayList<>(); - for (SpecializationData other : specializations) { - if (other.isUninitialized() || other.isGeneric()) { - 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) { - continue; - } - paramIds.add(Utils.getTypeId(param.getType())); - } - assert lastSize == -1 || lastSize == paramIds.size(); - if (lastSize != -1 && lastSize != paramIds.size()) { - throw new AssertionError(); - } - signatureChunks.add(paramIds); - lastSize = paramIds.size(); - } - - // reduce id vertically - for (int i = 0; i < lastSize; i++) { - String prev = null; - boolean allSame = true; - for (List signature : signatureChunks) { - String arg = signature.get(i); - if (prev == null) { - prev = arg; - continue; - } else if (!prev.equals(arg)) { - allSame = false; - break; - } - prev = arg; - } - - if (allSame) { - for (List signature : signatureChunks) { - signature.remove(i); - } - lastSize--; - } - } - - // reduce id horizontally - for (List signature : signatureChunks) { - if (signature.isEmpty()) { - continue; - } - String prev = null; - boolean allSame = true; - for (String arg : signature) { - if (prev == null) { - prev = arg; - continue; - } else if (!prev.equals(arg)) { - allSame = false; - break; - } - prev = arg; - } - - if (allSame) { - signature.clear(); - signature.add(prev); - } - } - - // create signatures - List signatures = new ArrayList<>(); - for (List signatureChunk : signatureChunks) { - StringBuilder b = new StringBuilder(); - if (signatureChunk.isEmpty()) { - b.append("Default"); - } else { - for (String s : signatureChunk) { - b.append(s); - } - } - signatures.add(b.toString()); - } - - Map counts = new HashMap<>(); - for (String s1 : signatures) { - Integer count = counts.get(s1); - if (count == null) { - count = 0; - } - count++; - counts.put(s1, count); - } - - for (String s : counts.keySet()) { - int count = counts.get(s); - if (count > 1) { - int number = 0; - for (ListIterator iterator = signatures.listIterator(); iterator.hasNext();) { - String s2 = iterator.next(); - if (s.equals(s2)) { - iterator.set(s2 + number); - number++; - } - } - } - } - - return signatures; - } - - private void verifyNode(NodeData nodeData, List elements) { - // verify order is not ambiguous - verifySpecializationOrder(nodeData); - - verifyMissingAbstractMethods(nodeData, elements); - - verifyConstructors(nodeData); - - verifyNamingConvention(nodeData.getShortCircuits(), "needs"); - - verifySpecializationThrows(nodeData); - } - - private static void verifyNodeChild(NodeChildData nodeChild) { - if (nodeChild.getNodeType() == null) { - nodeChild.addError("No valid node type could be resoleved."); - } - // FIXME verify node child - // FIXME verify node type set - } - - private static void verifyMissingAbstractMethods(NodeData nodeData, List originalElements) { - if (!nodeData.needsFactory()) { - // missing abstract methods only needs to be implemented - // if we need go generate factory for it. - return; - } - - List elements = new ArrayList<>(originalElements); - - Set unusedElements = new HashSet<>(elements); - for (TemplateMethod method : nodeData.getAllTemplateMethods()) { - unusedElements.remove(method.getMethod()); - } - if (nodeData.getExtensionElements() != null) { - unusedElements.removeAll(nodeData.getExtensionElements()); - } - - for (NodeChildData child : nodeData.getChildren()) { - if (child.getAccessElement() != null) { - unusedElements.remove(child.getAccessElement()); - } - } - - for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) { - if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) { - nodeData.addError("The type %s must implement the inherited abstract method %s.", Utils.getSimpleName(nodeData.getTemplateType()), Utils.getReadableSignature(unusedMethod)); - } - } - } - - private void verifyConstructors(NodeData nodeData) { - if (!nodeData.needsRewrites(context)) { - // no specialization constructor is needed if the node never rewrites. - return; - } - - TypeElement type = Utils.fromTypeMirror(nodeData.getNodeType()); - List constructors = ElementFilter.constructorsIn(type.getEnclosedElements()); - - boolean parametersFound = false; - for (ExecutableElement constructor : constructors) { - if (!constructor.getParameters().isEmpty()) { - parametersFound = true; - } - } - if (!parametersFound) { - return; - } - for (ExecutableElement e : constructors) { - if (e.getParameters().size() == 1) { - TypeMirror firstArg = e.getParameters().get(0).asType(); - if (Utils.typeEquals(firstArg, nodeData.getNodeType())) { - if (e.getModifiers().contains(Modifier.PRIVATE)) { - nodeData.addError("The specialization constructor must not be private."); - } else if (constructors.size() <= 1) { - nodeData.addError("The specialization constructor must not be the only constructor. The definition of an alternative constructor is required."); - } - return; - } - } - } - - // not found - nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type)); - } - - 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 HashMap<>(); - 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); - if (mirror != null) { - return mirror; - } - } - return null; - } - - private TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) { - TypeMirror inhertNodeType = context.getTruffleTypes().getNode(); - TypeMirror value = Utils.getAnnotationValue(TypeMirror.class, annotation, valueName); - if (Utils.typeEquals(inhertNodeType, value)) { - return parentType; - } else { - return value; - } - } - - private Element findGetter(List elements, String variableName, TypeMirror type) { - if (type == null) { - return null; - } - String methodName; - if (Utils.typeEquals(type, context.getType(boolean.class))) { - methodName = "is" + Utils.firstLetterUpperCase(variableName); - } else { - methodName = "get" + Utils.firstLetterUpperCase(variableName); - } - - for (ExecutableElement method : ElementFilter.methodsIn(elements)) { - if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.isAssignable(context, type, method.getReturnType())) { - return method; - } - } - 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; - } - } - 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 f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +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.codegen.processor.node; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.*; - -public class ShortCircuitData extends TemplateMethod { - - private ShortCircuitData genericShortCircuitMethod; - private final String valueName; - - public ShortCircuitData(TemplateMethod template, String valueName) { - super(template); - this.valueName = valueName; - } - - public String getValueName() { - return valueName; - } - - public void setGenericShortCircuitMethod(ShortCircuitData genericShortCircuitMethod) { - this.genericShortCircuitMethod = genericShortCircuitMethod; - } - - public boolean isGeneric() { - return genericShortCircuitMethod == null; - } - - public ShortCircuitData getGeneric() { - if (isGeneric()) { - return this; - } else { - return genericShortCircuitMethod; - } - } - - public boolean isCompatibleTo(SpecializationData specialization) { - if (isGeneric() && specialization.isGeneric()) { - return true; - } - - for (ActualParameter param : getParameters()) { - ActualParameter specializationParam = specialization.findParameter(param.getLocalName()); - if (!Utils.typeEquals(param.getType(), specializationParam.getType())) { - return false; - } - } - return true; - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +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.codegen.processor.node; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; -import com.oracle.truffle.codegen.processor.template.*; - -public class ShortCircuitParser extends NodeMethodParser { - - private final Set shortCircuitValues; - - public ShortCircuitParser(ProcessorContext context, NodeData node) { - super(context, node); - - shortCircuitValues = new HashSet<>(); - NodeChildData[] shortCircuitFields = node.filterFields(ExecutionKind.SHORT_CIRCUIT); - for (NodeChildData field : shortCircuitFields) { - shortCircuitValues.add(field.getName()); - } - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - String shortCircuitValue = Utils.getAnnotationValue(String.class, mirror, "value"); - return createDefaultMethodSpec(method, mirror, true, shortCircuitValue); - } - - @Override - protected ParameterSpec createReturnParameterSpec() { - return new ParameterSpec("has", getContext().getType(boolean.class)); - } - - @Override - public ShortCircuitData create(TemplateMethod method) { - String shortCircuitValue = Utils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value"); - - if (!shortCircuitValues.contains(shortCircuitValue)) { - method.addError("Invalid short circuit value %s.", shortCircuitValue); - } - - return new ShortCircuitData(method, shortCircuitValue); - } - - @Override - public Class getAnnotationType() { - return ShortCircuit.class; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,251 +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.codegen.processor.node; - -import java.util.*; - -import javax.lang.model.type.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.*; -import com.oracle.truffle.codegen.processor.typesystem.*; - -public class SpecializationData extends TemplateMethod { - - private final int order; - private final boolean generic; - private final boolean polymorphic; - private final boolean uninitialized; - 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) { - super(template); - this.order = order; - this.generic = false; - this.uninitialized = false; - this.polymorphic = false; - this.exceptions = exceptions; - - for (SpecializationThrowsData exception : exceptions) { - exception.setSpecialization(this); - } - } - - 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 void setReachable(boolean reachable) { - this.reachable = reachable; - } - - public boolean isReachable() { - return reachable; - } - - public boolean isPolymorphic() { - return polymorphic; - } - - @Override - protected List findChildContainers() { - List sinks = new ArrayList<>(); - if (exceptions != null) { - sinks.addAll(exceptions); - } - if (guards != null) { - sinks.addAll(guards); - } - return sinks; - } - - public boolean isGenericSpecialization(ProcessorContext context) { - if (isGeneric()) { - return true; - } - if (hasRewrite(context)) { - return false; - } - - for (ActualParameter parameter : getParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - NodeChildData child = getNode().findChild(parameter.getSpecification().getName()); - if (child == null) { - continue; - } - if (!parameter.getTypeSystemType().isGeneric()) { - return false; - } - } - - return true; - } - - public boolean hasRewrite(ProcessorContext context) { - if (!getExceptions().isEmpty()) { - return true; - } - if (!getGuards().isEmpty()) { - return true; - } - 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()); - if (type.hasUnexpectedValue(context)) { - return true; - } - if (type.getReturnType().getTypeSystemType().needsCastTo(context, parameter.getTypeSystemType())) { - return true; - } - - } - return false; - } - - @Override - public int compareBySignature(TemplateMethod other) { - if (this == other) { - return 0; - } else if (!(other instanceof SpecializationData)) { - return super.compareBySignature(other); - } - - SpecializationData m2 = (SpecializationData) other; - - 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()) { - throw new UnsupportedOperationException("Cannot compare two specializations with different templates."); - } - - return super.compareBySignature(m2); - } - - public NodeData getNode() { - return node; - } - - public void setNode(NodeData node) { - this.node = node; - } - - public void setGuards(List guards) { - this.guards = guards; - } - - public void setGuardDefinitions(List guardDefinitions) { - this.guardDefinitions = guardDefinitions; - } - - public int getOrder() { - return order; - } - - public boolean isGeneric() { - return generic; - } - - public boolean isUninitialized() { - return uninitialized; - } - - public List getExceptions() { - return exceptions; - } - - public List getGuardDefinitions() { - return guardDefinitions; - } - - public List getGuards() { - return guards; - } - - public void setShortCircuits(List shortCircuits) { - this.shortCircuits = shortCircuits; - } - - public List getShortCircuits() { - return shortCircuits; - } - - public List getAssumptions() { - return assumptions; - } - - void setAssumptions(List assumptions) { - this.assumptions = assumptions; - } - - public SpecializationData findNextSpecialization() { - List specializations = node.getSpecializations(); - for (int i = 0; i < specializations.size() - 1; i++) { - if (specializations.get(i) == this) { - return specializations.get(i + 1); - } - } - return null; - } - - public boolean hasDynamicGuards() { - return !getGuards().isEmpty(); - } - - @Override - public String toString() { - return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getSignature()); - } - - public void forceFrame(TypeMirror frameType) { - if (getParameters().isEmpty() || !Utils.typeEquals(getParameters().get(0).getType(), frameType)) { - ParameterSpec frameSpec = getSpecification().findParameterSpec("frame"); - getParameters().add(0, new ActualParameter(frameSpec, frameType, -1, false)); - } - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationGuardData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationGuardData.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +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.codegen.processor.node; - -import javax.lang.model.element.*; - -import com.oracle.truffle.codegen.processor.template.*; -import com.oracle.truffle.codegen.processor.typesystem.*; - -public class SpecializationGuardData extends MessageContainer { - - private final SpecializationData specialization; - private final AnnotationValue value; - private final String guardMethod; - private final boolean onSpecialization; - private final boolean onExecution; - - private GuardData guardDeclaration; - - public SpecializationGuardData(SpecializationData specialization, AnnotationValue value, String guardMethod, boolean onSpecialization, boolean onExecution) { - this.specialization = specialization; - this.guardMethod = guardMethod; - this.onSpecialization = onSpecialization; - this.onExecution = onExecution; - this.value = value; - } - - @Override - public Element getMessageElement() { - return specialization.getMessageElement(); - } - - @Override - public AnnotationMirror getMessageAnnotation() { - return specialization.getMessageAnnotation(); - } - - @Override - public AnnotationValue getMessageAnnotationValue() { - return value; - } - - public String getGuardMethod() { - return guardMethod; - } - - public boolean isOnExecution() { - return onExecution; - } - - public boolean isOnSpecialization() { - return onSpecialization; - } - - public void setGuardDeclaration(GuardData compatibleGuard) { - this.guardDeclaration = compatibleGuard; - } - - public GuardData getGuardDeclaration() { - return guardDeclaration; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerData.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +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.codegen.processor.node; - -import com.oracle.truffle.codegen.processor.template.*; - -public class SpecializationListenerData extends TemplateMethod { - - public SpecializationListenerData(TemplateMethod method) { - super(method); - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /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.codegen.processor.node; - -import java.lang.annotation.*; - -import javax.lang.model.element.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.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) { - return new SpecializationListenerData(method); - } - - @Override - public Class getAnnotationType() { - return SpecializationListener.class; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +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.codegen.processor.node; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.*; - -public class SpecializationMethodParser extends NodeMethodParser { - - public SpecializationMethodParser(ProcessorContext context, NodeData operation) { - super(context, operation); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return createDefaultMethodSpec(method, mirror, true, null); - } - - @Override - public SpecializationData create(TemplateMethod method) { - return parseSpecialization(method); - } - - @Override - public Class getAnnotationType() { - return Specialization.class; - } - - private SpecializationData parseSpecialization(TemplateMethod method) { - int order = Utils.getAnnotationValue(Integer.class, method.getMarkerAnnotation(), "order"); - if (order < 0 && order != Specialization.DEFAULT_ORDER) { - method.addError("Invalid order attribute %d. The value must be >= 0 or the default value."); - return null; - } - - AnnotationValue rewriteValue = Utils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn"); - List exceptionTypes = Utils.getAnnotationValueList(TypeMirror.class, method.getMarkerAnnotation(), "rewriteOn"); - List exceptionData = new ArrayList<>(); - for (TypeMirror exceptionType : exceptionTypes) { - SpecializationThrowsData throwsData = new SpecializationThrowsData(method.getMarkerAnnotation(), rewriteValue, exceptionType); - if (!Utils.canThrowType(method.getMethod().getThrownTypes(), exceptionType)) { - throwsData.addError("Method must specify a throws clause with the exception type '%s'.", Utils.getQualifiedName(exceptionType)); - } - exceptionData.add(throwsData); - } - - Collections.sort(exceptionData, new Comparator() { - - @Override - public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) { - return Utils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass()); - } - }); - SpecializationData specialization = new SpecializationData(method, order, exceptionData); - List guardDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); - specialization.setGuardDefinitions(guardDefs); - - List assumptionDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "assumptions"); - specialization.setAssumptions(assumptionDefs); - - for (String assumption : assumptionDefs) { - if (!getNode().getAssumptions().contains(assumption)) { - specialization.addError("Undeclared assumption '%s' used. Use @NodeAssumptions to declare them.", assumption); - } - } - - return specialization; - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationThrowsData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationThrowsData.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +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.codegen.processor.node; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.template.*; - -public class SpecializationThrowsData extends MessageContainer { - - private final AnnotationValue annotationValue; - private final AnnotationMirror annotationMirror; - private final TypeMirror javaClass; - private SpecializationData specialization; - - public SpecializationThrowsData(AnnotationMirror annotationMirror, AnnotationValue value, TypeMirror javaClass) { - this.annotationMirror = annotationMirror; - this.annotationValue = value; - this.javaClass = javaClass; - } - - void setSpecialization(SpecializationData specialization) { - this.specialization = specialization; - } - - @Override - public Element getMessageElement() { - return specialization.getMessageElement(); - } - - @Override - public AnnotationMirror getMessageAnnotation() { - return annotationMirror; - } - - @Override - public AnnotationValue getMessageAnnotationValue() { - return annotationValue; - } - - public TypeMirror getJavaClass() { - return javaClass; - } - - public SpecializationData getSpecialization() { - return specialization; - } - - public AnnotationMirror getAnnotationMirror() { - return annotationMirror; - } - - public SpecializationData getTransitionTo() { - return specialization.findNextSpecialization(); - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +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.codegen.processor.template; - -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.typesystem.*; - -public class ActualParameter { - - private final ParameterSpec specification; - private TypeData typeSystemType; - private TemplateMethod method; - private final String localName; - private final int index; - private final boolean implicit; - private final TypeMirror type; - - public ActualParameter(ParameterSpec specification, TypeMirror actualType, int index, boolean implicit) { - this.specification = specification; - this.type = actualType; - this.typeSystemType = null; - - this.index = index; - this.implicit = implicit; - String valueName = specification.getName() + "Value"; - - if (specification.isIndexed()) { - valueName += index; - } - this.localName = valueName; - } - - public ActualParameter(ParameterSpec specification, TypeData actualType, int index, boolean implicit) { - this(specification, actualType.getPrimitiveType(), index, implicit); - this.typeSystemType = actualType; - } - - public ActualParameter(ActualParameter parameter, TypeData otherType) { - this(parameter.specification, otherType, parameter.index, parameter.implicit); - } - - public ActualParameter(ActualParameter parameter) { - this.specification = parameter.specification; - this.type = parameter.type; - this.typeSystemType = parameter.typeSystemType; - this.index = parameter.index; - this.implicit = parameter.implicit; - this.localName = parameter.localName; - } - - public boolean isImplicit() { - return implicit; - } - - public int getIndex() { - return index; - } - - public String getLocalName() { - return localName; - } - - void setMethod(TemplateMethod method) { - this.method = method; - } - - public ParameterSpec getSpecification() { - return specification; - } - - public TemplateMethod getMethod() { - return method; - } - - public TypeMirror getType() { - return type; - } - - public TypeData getTypeSystemType() { - return typeSystemType; - } - - public ActualParameter getPreviousParameter() { - return method.getPreviousParam(this); - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +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.codegen.processor.template; - -import static com.oracle.truffle.codegen.processor.Utils.*; -import static javax.lang.model.element.Modifier.*; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.ast.*; - -public abstract class ClassElementFactory extends CodeElementFactory { - - public ClassElementFactory(ProcessorContext context) { - super(context); - } - - @Override - protected abstract CodeTypeElement create(M m); - - @Override - public CodeTypeElement getElement() { - return (CodeTypeElement) super.getElement(); - } - - protected CodeExecutableElement createConstructorUsingFields(Set modifiers, CodeTypeElement clazz) { - CodeExecutableElement method = new CodeExecutableElement(modifiers, null, clazz.getSimpleName().toString()); - CodeTreeBuilder builder = method.createBuilder(); - TypeElement superClass = fromTypeMirror(clazz.getSuperclass()); - ExecutableElement constructor = findConstructor(superClass); - if (constructor != null && constructor.getParameters().size() > 0) { - builder.startStatement(); - builder.startSuperCall(); - for (VariableElement parameter : constructor.getParameters()) { - method.addParameter(new CodeVariableElement(parameter.asType(), parameter.getSimpleName().toString())); - builder.string(parameter.getSimpleName().toString()); - } - builder.end(); // super - builder.end(); // statement - } - - for (VariableElement field : clazz.getFields()) { - if (field.getModifiers().contains(STATIC)) { - continue; - } - String fieldName = field.getSimpleName().toString(); - method.addParameter(new CodeVariableElement(field.asType(), fieldName)); - builder.startStatement(); - builder.string("this."); - builder.string(fieldName); - builder.string(" = "); - if (isAssignable(getContext(), field.asType(), getContext().getTruffleTypes().getNode())) { - builder.string("adoptChild(").string(fieldName).string(")"); - } else { - builder.string(fieldName); - } - builder.end(); // statement - } - - return method; - } - - private static ExecutableElement findConstructor(TypeElement clazz) { - List constructors = ElementFilter.constructorsIn(clazz.getEnclosedElements()); - if (constructors.isEmpty()) { - return null; - } else { - return constructors.get(0); - } - } - - protected CodeExecutableElement createSuperConstructor(TypeElement type, ExecutableElement element) { - if (element.getModifiers().contains(Modifier.PRIVATE)) { - return null; - } - CodeExecutableElement executable = CodeExecutableElement.clone(getContext().getEnvironment(), element); - executable.setReturnType(null); - executable.setSimpleName(CodeNames.of(type.getSimpleName().toString())); - CodeTreeBuilder b = executable.createBuilder(); - b.startStatement(); - b.startSuperCall(); - for (VariableElement v : element.getParameters()) { - b.string(v.getSimpleName().toString()); - } - b.end(); - b.end(); - - return executable; - } - - protected CodeTypeElement createClass(Template model, Set modifiers, String simpleName, TypeMirror superType, boolean enumType) { - TypeElement templateType = model.getTemplateType(); - - PackageElement pack = getContext().getEnvironment().getElementUtils().getPackageOf(templateType); - CodeTypeElement clazz = new CodeTypeElement(modifiers, enumType ? ElementKind.ENUM : ElementKind.CLASS, pack, simpleName); - TypeMirror resolvedSuperType = superType; - if (resolvedSuperType == null) { - resolvedSuperType = getContext().getType(Object.class); - } - clazz.setSuperClass(resolvedSuperType); - - CodeAnnotationMirror generatedByAnnotation = new CodeAnnotationMirror((DeclaredType) getContext().getType(GeneratedBy.class)); - generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("value"), new CodeAnnotationValue(templateType.asType())); - if (model.getTemplateMethodName() != null) { - generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("methodName"), new CodeAnnotationValue(model.getTemplateMethodName())); - } - - clazz.addAnnotationMirror(generatedByAnnotation); - - context.registerType(model.getTemplateType(), clazz.asType()); - - return clazz; - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CodeElementFactory.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CodeElementFactory.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +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.codegen.processor.template; - -import javax.lang.model.element.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.ast.*; - -public abstract class CodeElementFactory { - - protected final ProcessorContext context; - private M model; - - private CodeElement element; - - public CodeElementFactory(ProcessorContext context) { - this.context = context; - } - - protected abstract CodeElement create(M m); - - @SuppressWarnings("unused") - protected void createChildren(M m) { - } - - @SuppressWarnings("unchecked") - public CodeElement process(CodeElement parent, M m) { - model = m; - element = (CodeElement) create(model); - if (parent != null) { - parent.add(element); - } - if (element != null) { - createChildren(model); - } - return element; - } - - public CodeElement getElement() { - return element; - } - - protected void add(CodeElementFactory factory, MO m) { - factory.process(this.element, m); - } - - public ProcessorContext getContext() { - return context; - } - - public M getModel() { - return model; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CompilationUnitFactory.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CompilationUnitFactory.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +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.codegen.processor.template; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.ast.*; - -public abstract class CompilationUnitFactory extends CodeElementFactory { - - public CompilationUnitFactory(ProcessorContext context) { - super(context); - } - - @Override - public final CodeCompilationUnit create(M m) { - return new CodeCompilationUnit(); - } - - @Override - public CodeCompilationUnit process(CodeElement parent, M m) { - return (CodeCompilationUnit) super.process(parent, m); - } - - @Override - protected abstract void createChildren(M m); - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/JavaName.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/JavaName.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +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.codegen.processor.template; - -import java.util.*; -import java.util.regex.*; - -public final class JavaName { - - private static final String[] RESERVED_NAMES = new String[]{"abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package", "synchronized", "boolean", "do", "if", - "private", "this", "break", "double", "implements", "protected", "throw", "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", - "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", "finally", "long", "strictfp", "volatile", "const", "float", "native", "super", - "while"}; - - private static final Set RESERVED_NAMES_SET = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(RESERVED_NAMES))); - - private static final Pattern VALID_JAVA_NAME_PATTERN = Pattern.compile("[_a-zA-z][_a-zA-Z0-9]*"); - - private JavaName() { - super(); - } - - public static boolean isReserved(String name) { - return RESERVED_NAMES_SET.contains(name); - } - - public static boolean isValid(String typeName) { - return VALID_JAVA_NAME_PATTERN.matcher(typeName).matches(); - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MessageContainer.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MessageContainer.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,191 +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.codegen.processor.template; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.tools.Diagnostic.Kind; - -import com.oracle.truffle.codegen.processor.*; - -public abstract class MessageContainer { - - private final List messages = new ArrayList<>(); - - public final void addWarning(String text, Object... params) { - getMessages().add(new Message(null, this, String.format(text, params), Kind.WARNING)); - } - - public final void addError(String text, Object... params) { - addError(null, text, params); - } - - public final void addError(AnnotationValue value, String text, Object... params) { - getMessages().add(new Message(value, this, String.format(text, params), Kind.ERROR)); - } - - protected List findChildContainers() { - return Collections.emptyList(); - } - - public abstract Element getMessageElement(); - - public final void emitMessages(TypeElement baseElement, Log log) { - emitMessagesImpl(baseElement, log, new HashSet()); - } - - private void emitMessagesImpl(TypeElement baseElement, Log log, Set visitedSinks) { - for (Message message : getMessages()) { - emitDefault(baseElement, log, message); - } - - for (MessageContainer sink : findChildContainers()) { - if (visitedSinks.contains(sink)) { - continue; - } - - visitedSinks.add(sink); - sink.emitMessagesImpl(baseElement, log, visitedSinks); - } - } - - private void emitDefault(TypeElement baseType, Log log, Message message) { - TypeElement rootEnclosing = Utils.findRootEnclosingType(getMessageElement()); - if (rootEnclosing != null && Utils.typeEquals(baseType.asType(), rootEnclosing.asType()) && this == message.getOriginalContainer()) { - log.message(message.getKind(), getMessageElement(), getMessageAnnotation(), getMessageAnnotationValue(), message.getText()); - } else { - MessageContainer original = message.getOriginalContainer(); - log.message(message.getKind(), baseType, null, null, wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText())); - } - } - - private static String wrapText(Element element, AnnotationMirror mirror, String text) { - StringBuilder b = new StringBuilder(); - if (element != null) { - b.append("Element " + element.toString()); - } - if (mirror != null) { - b.append(" at annotation @" + Utils.getSimpleName(mirror.getAnnotationType())); - } - - if (b.length() > 0) { - b.append(" is erroneous: ").append(text); - return b.toString(); - } else { - return text; - } - } - - public AnnotationMirror getMessageAnnotation() { - return null; - } - - public AnnotationValue getMessageAnnotationValue() { - return null; - } - - public final boolean hasErrors() { - return hasErrorsImpl(new HashSet()); - } - - public final List collectMessages() { - List collectedMessages = new ArrayList<>(); - collectMessagesImpl(collectedMessages, new HashSet()); - return collectedMessages; - } - - private void collectMessagesImpl(List collectedMessages, Set visitedSinks) { - collectedMessages.addAll(getMessages()); - for (MessageContainer sink : findChildContainers()) { - if (visitedSinks.contains(sink)) { - return; - } - - visitedSinks.add(sink); - sink.collectMessagesImpl(collectedMessages, visitedSinks); - } - } - - private boolean hasErrorsImpl(Set visitedSinks) { - for (Message msg : getMessages()) { - if (msg.getKind() == Kind.ERROR) { - return true; - } - } - for (MessageContainer sink : findChildContainers()) { - if (visitedSinks.contains(sink)) { - return false; - } - - visitedSinks.add(sink); - - if (sink.hasErrorsImpl(visitedSinks)) { - return true; - } - } - return false; - } - - public List getMessages() { - return messages; - } - - public static final class Message { - - private final MessageContainer originalContainer; - private final AnnotationValue annotationValue; - private final String text; - private final Kind kind; - - public Message(AnnotationValue annotationValue, MessageContainer originalContainer, String text, Kind kind) { - this.annotationValue = annotationValue; - this.originalContainer = originalContainer; - this.text = text; - this.kind = kind; - } - - public AnnotationValue getAnnotationValue() { - return annotationValue; - } - - public MessageContainer getOriginalContainer() { - return originalContainer; - } - - public String getText() { - return text; - } - - public Kind getKind() { - return kind; - } - - @Override - public String toString() { - return kind + ": " + text; - } - - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,228 +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.codegen.processor.template; - -import java.util.*; - -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; - -public class MethodSpec { - - private final List implicitRequiredTypes = new ArrayList<>(); - - private final ParameterSpec returnType; - private final List optional = new ArrayList<>(); - private final List required = new ArrayList<>(); - - private boolean variableRequiredArguments; - private List typeDefinitions; - - public MethodSpec(ParameterSpec returnType) { - this.returnType = returnType; - } - - public void setVariableRequiredArguments(boolean variableArguments) { - this.variableRequiredArguments = variableArguments; - } - - public boolean isVariableRequiredArguments() { - return variableRequiredArguments; - } - - public void addImplicitRequiredType(TypeMirror type) { - this.implicitRequiredTypes.add(type); - } - - public void addOptional(ParameterSpec spec) { - optional.add(spec); - } - - public ParameterSpec addRequired(ParameterSpec spec) { - required.add(spec); - return spec; - } - - public List getImplicitRequiredTypes() { - return implicitRequiredTypes; - } - - public ParameterSpec getReturnType() { - return returnType; - } - - public List getRequired() { - return required; - } - - public List getOptional() { - return optional; - } - - public List getAll() { - List specs = new ArrayList<>(); - specs.add(getReturnType()); - specs.addAll(getOptional()); - specs.addAll(getRequired()); - return specs; - } - - public ParameterSpec findParameterSpec(String name) { - for (ParameterSpec spec : getAll()) { - if (spec.getName().equals(name)) { - return spec; - } - } - return null; - } - - public void applyTypeDefinitions(String prefix) { - this.typeDefinitions = createTypeDefinitions(prefix); - } - - private List createTypeDefinitions(String prefix) { - List typeDefs = new ArrayList<>(); - - int defIndex = 0; - for (ParameterSpec spec : getAll()) { - List allowedTypes = spec.getAllowedTypes(); - List types = spec.getAllowedTypes(); - if (types != null && allowedTypes.size() > 1) { - TypeDef foundDef = null; - for (TypeDef def : typeDefs) { - if (allowedTypes.equals(def.getTypes())) { - foundDef = def; - break; - } - } - if (foundDef == null) { - foundDef = new TypeDef(types, prefix + defIndex); - typeDefs.add(foundDef); - defIndex++; - } - - spec.setTypeDefinition(foundDef); - } - } - - return typeDefs; - } - - public String toSignatureString(String methodName) { - StringBuilder b = new StringBuilder(); - b.append(" "); - b.append(createTypeSignature(returnType, true)); - - b.append(" "); - b.append(methodName); - b.append("("); - - String sep = ""; - - for (ParameterSpec optionalSpec : getOptional()) { - b.append(sep); - b.append("["); - b.append(createTypeSignature(optionalSpec, false)); - b.append("]"); - sep = ", "; - } - - for (ParameterSpec requiredSpec : getRequired()) { - b.append(sep); - if (requiredSpec.getCardinality() == Cardinality.MANY) { - b.append("{"); - } - b.append(createTypeSignature(requiredSpec, false)); - if (requiredSpec.getCardinality() == Cardinality.MANY) { - b.append("}"); - } - sep = ", "; - } - - b.append(")"); - - if (typeDefinitions != null && !typeDefinitions.isEmpty()) { - b.append("\n\n"); - - String lineSep = ""; - for (TypeDef def : typeDefinitions) { - b.append(lineSep); - b.append(" <").append(def.getName()).append(">"); - b.append(" = {"); - String separator = ""; - for (TypeMirror type : def.getTypes()) { - b.append(separator).append(Utils.getSimpleName(type)); - separator = ", "; - } - b.append("}"); - lineSep = "\n"; - - } - } - return b.toString(); - } - - private static String createTypeSignature(ParameterSpec spec, boolean typeOnly) { - StringBuilder builder = new StringBuilder(); - TypeDef foundTypeDef = spec.getTypeDefinition(); - if (foundTypeDef != null) { - builder.append("<" + foundTypeDef.getName() + ">"); - } else if (spec.getAllowedTypes().size() >= 1) { - builder.append(Utils.getSimpleName(spec.getAllowedTypes().get(0))); - } else { - builder.append("void"); - } - if (!typeOnly) { - builder.append(" "); - builder.append(spec.getName()); - } - return builder.toString(); - } - - @Override - public String toString() { - return toSignatureString("methodName"); - } - - static class TypeDef { - - private final List types; - private final String name; - - public TypeDef(List types, String name) { - this.types = types; - this.name = name; - } - - public List getTypes() { - return types; - } - - public String getName() { - return name; - } - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +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.codegen.processor.template; - -import java.util.*; - -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; -import com.oracle.truffle.codegen.processor.template.MethodSpec.TypeDef; - -public class ParameterSpec { - - 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; - - 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(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.allowedTypes = allowedTypes; - } - - void setTypeDefinition(TypeDef typeDefinition) { - this.typeDefinition = typeDefinition; - } - - TypeDef getTypeDefinition() { - return typeDefinition; - } - - public void setSignature(boolean signature) { - this.signature = signature; - } - - public void setLocal(boolean local) { - this.local = local; - } - - public boolean isSignature() { - return signature; - } - - 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; - } - - public boolean matches(TypeMirror actualType) { - for (TypeMirror mirror : allowedTypes) { - if (Utils.typeEquals(actualType, mirror)) { - return true; - } - } - return false; - } - - @Override - public String toString() { - return toSignatureString(false); - } - - public String toSignatureString(boolean typeOnly) { - StringBuilder builder = new StringBuilder(); - if (typeDefinition != null) { - builder.append("<" + typeDefinition.getName() + ">"); - } else if (getAllowedTypes().size() >= 1) { - builder.append(Utils.getSimpleName(getAllowedTypes().get(0))); - } else { - builder.append("void"); - } - if (!typeOnly) { - builder.append(" "); - builder.append(getName()); - } - return builder.toString(); - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/Template.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/Template.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +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.codegen.processor.template; - -import java.util.*; - -import javax.lang.model.element.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.api.element.*; -import com.oracle.truffle.codegen.processor.typesystem.*; - -public abstract class Template extends MessageContainer { - - private final TypeElement templateType; - private final String templateMethodName; - private final AnnotationMirror annotation; - - private List extensionElements; - - public Template(TypeElement templateType, String templateMethodName, AnnotationMirror annotation) { - this.templateType = templateType; - this.templateMethodName = templateMethodName; - this.annotation = annotation; - } - - public abstract TypeSystemData getTypeSystem(); - - @Override - public Element getMessageElement() { - return templateType; - } - - @Override - protected List findChildContainers() { - return Collections.emptyList(); - } - - public String getTemplateMethodName() { - return templateMethodName; - } - - public TypeElement getTemplateType() { - return templateType; - } - - public AnnotationMirror getTemplateTypeAnnotation() { - return annotation; - } - - public List getExtensionElements() { - return extensionElements; - } - - public void setExtensionElements(List extensionMethods) { - this.extensionElements = extensionMethods; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "[" + Utils.getSimpleName(getTemplateType()) + "]"; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,393 +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.codegen.processor.template; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.typesystem.*; - -/** - * Note: this class has a natural ordering that is inconsistent with equals. - */ -public class TemplateMethod extends MessageContainer implements Comparable { - - private String id; - private final Template template; - private final MethodSpec specification; - private final ExecutableElement method; - private final AnnotationMirror markerAnnotation; - private ActualParameter returnType; - private List parameters; - - public TemplateMethod(String id, Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType, - List parameters) { - this.template = template; - this.specification = specification; - this.method = method; - this.markerAnnotation = markerAnnotation; - this.returnType = returnType; - this.parameters = new ArrayList<>(); - for (ActualParameter param : parameters) { - ActualParameter newParam = new ActualParameter(param); - this.parameters.add(newParam); - newParam.setMethod(this); - } - this.id = id; - } - - public TemplateMethod(TemplateMethod method) { - this(method.id, method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters); - getMessages().addAll(method.getMessages()); - } - - public TemplateMethod(TemplateMethod method, ExecutableElement executable) { - this(method.id, method.template, method.specification, executable, method.markerAnnotation, method.returnType, method.parameters); - getMessages().addAll(method.getMessages()); - } - - public void setParameters(List parameters) { - this.parameters = parameters; - } - - @Override - public Element getMessageElement() { - return method; - } - - @Override - public AnnotationMirror getMessageAnnotation() { - return markerAnnotation; - } - - @Override - protected List findChildContainers() { - return Collections.emptyList(); - } - - public void setId(String id) { - this.id = id; - } - - public String getId() { - return id; - } - - public Template getTemplate() { - return template; - } - - public MethodSpec getSpecification() { - return specification; - } - - public ActualParameter getReturnType() { - return returnType; - } - - public void replaceParameter(String localName, ActualParameter newParameter) { - if (returnType.getLocalName().equals(localName)) { - returnType = newParameter; - returnType.setMethod(this); - } - - for (ListIterator iterator = parameters.listIterator(); iterator.hasNext();) { - ActualParameter parameter = iterator.next(); - if (parameter.getLocalName().equals(localName)) { - iterator.set(newParameter); - newParameter.setMethod(this); - } - } - } - - public List getRequiredParameters() { - List requiredParameters = new ArrayList<>(); - for (ActualParameter parameter : getParameters()) { - if (getSpecification().getRequired().contains(parameter.getSpecification())) { - requiredParameters.add(parameter); - } - } - return requiredParameters; - } - - public List getParameters() { - return parameters; - } - - public List findParameters(ParameterSpec spec) { - List foundParameters = new ArrayList<>(); - for (ActualParameter param : getReturnTypeAndParameters()) { - if (param.getSpecification().equals(spec)) { - foundParameters.add(param); - } - } - return foundParameters; - } - - public ActualParameter findParameter(String valueName) { - for (ActualParameter param : getReturnTypeAndParameters()) { - if (param.getLocalName().equals(valueName)) { - return param; - } - } - return null; - } - - public List getReturnTypeAndParameters() { - List allParameters = new ArrayList<>(getParameters().size() + 1); - if (getReturnType() != null) { - allParameters.add(getReturnType()); - } - allParameters.addAll(getParameters()); - return Collections.unmodifiableList(allParameters); - } - - public boolean canBeAccessedByInstanceOf(ProcessorContext context, TypeMirror type) { - TypeMirror methodType = Utils.findNearestEnclosingType(getMethod()).asType(); - return Utils.isAssignable(context, type, methodType) || Utils.isAssignable(context, methodType, type); - } - - public ExecutableElement getMethod() { - return method; - } - - public String getMethodName() { - if (getMethod() != null) { - return getMethod().getSimpleName().toString(); - } else { - return "$synthetic"; - } - } - - public AnnotationMirror getMarkerAnnotation() { - return markerAnnotation; - } - - @Override - public String toString() { - return String.format("%s [id = %s, method = %s]", getClass().getSimpleName(), getId(), getMethod()); - } - - public ActualParameter getPreviousParam(ActualParameter searchParam) { - ActualParameter prev = null; - for (ActualParameter param : getParameters()) { - if (param == searchParam) { - return prev; - } - prev = param; - } - return prev; - } - - public Signature getSignature() { - Signature signature = new Signature(); - for (ActualParameter parameter : getReturnTypeAndParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - TypeData typeData = parameter.getTypeSystemType(); - if (typeData != null) { - signature.types.add(typeData); - } - } - return signature; - } - - public void updateSignature(Signature signature) { - assert signature.size() >= 1; - int signatureIndex = 0; - for (ActualParameter parameter : getReturnTypeAndParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - TypeData newType = signature.get(signatureIndex++); - if (!parameter.getTypeSystemType().equals(newType)) { - replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, newType)); - } - } - } - - @Override - public int compareTo(TemplateMethod o) { - if (this == o) { - return 0; - } - - int compare = compareBySignature(o); - if (compare == 0) { - // if signature sorting failed sort by id - compare = getId().compareTo(o.getId()); - } - if (compare == 0) { - // if still no difference sort by enclosing type name - TypeElement enclosingType1 = Utils.findNearestEnclosingType(getMethod()); - TypeElement enclosingType2 = Utils.findNearestEnclosingType(o.getMethod()); - compare = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString()); - } - return compare; - } - - public List getParametersAfter(ActualParameter genericParameter) { - boolean found = false; - List foundParameters = new ArrayList<>(); - for (ActualParameter param : getParameters()) { - if (param.getLocalName().equals(genericParameter.getLocalName())) { - found = true; - } else if (found) { - foundParameters.add(param); - } - } - return foundParameters; - } - - public int compareBySignature(TemplateMethod compareMethod) { - TypeSystemData typeSystem = getTemplate().getTypeSystem(); - if (typeSystem != compareMethod.getTemplate().getTypeSystem()) { - throw new IllegalStateException("Cannot compare two methods with different type systems."); - } - - Signature signature1 = getSignature(); - Signature signature2 = compareMethod.getSignature(); - if (signature1.size() != signature2.size()) { - return signature2.size() - signature1.size(); - } - - int result = 0; - for (int i = 1; i < signature1.size(); i++) { - int typeResult = compareActualParameter(typeSystem, signature1.get(i), signature2.get(i)); - if (result == 0) { - result = typeResult; - } else if (typeResult != 0 && Math.signum(result) != Math.signum(typeResult)) { - // We cannot define an order. - return 0; - } - } - if (result == 0 && signature1.size() > 0) { - result = compareActualParameter(typeSystem, signature1.get(0), signature2.get(0)); - } - - return result; - } - - private static int compareActualParameter(TypeSystemData typeSystem, TypeData t1, TypeData t2) { - int index1 = typeSystem.findType(t1); - int index2 = typeSystem.findType(t2); - return index1 - index2; - } - - public static class Signature implements Iterable, Comparable { - - final List types; - - public Signature() { - this.types = new ArrayList<>(); - } - - public Signature(List signature) { - this.types = signature; - } - - @Override - public int hashCode() { - return types.hashCode(); - } - - public int compareTo(Signature o) { - if (o.size() != size()) { - return size() - o.size(); - } - - int typeSum = 0; - int otherTypeSum = 0; - for (int i = 0; i < types.size(); i++) { - TypeData type = types.get(i); - TypeData otherType = o.get(i); - typeSum += type.isGeneric() ? 1 : 0; - otherTypeSum += otherType.isGeneric() ? 1 : 0; - } - - return typeSum - otherTypeSum; - } - - public int size() { - return types.size(); - } - - public TypeData get(int index) { - return types.get(index); - } - - public Signature combine(Signature genericSignature, Signature other) { - assert types.size() == other.types.size(); - assert genericSignature.types.size() == other.types.size(); - - if (this.equals(other)) { - return this; - } - - Signature signature = new Signature(); - for (int i = 0; i < types.size(); i++) { - TypeData type1 = types.get(i); - TypeData type2 = other.types.get(i); - if (type1.equals(type2)) { - signature.types.add(type1); - } else { - signature.types.add(genericSignature.types.get(i)); - } - } - return signature; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Signature) { - return ((Signature) obj).types.equals(types); - } - return super.equals(obj); - } - - public Iterator iterator() { - return types.iterator(); - } - - @Override - public String toString() { - return types.toString(); - } - - public boolean hasAnyParameterMatch(Signature other) { - for (int i = 1; i < types.size(); i++) { - TypeData type1 = types.get(i); - TypeData type2 = other.types.get(i); - if (type1.equals(type2)) { - return true; - } - } - return false; - } - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,338 +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.codegen.processor.template; - -import static com.oracle.truffle.codegen.processor.Utils.*; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; -import com.oracle.truffle.codegen.processor.typesystem.*; - -public abstract class TemplateMethodParser { - - private final ProcessorContext context; - - protected final T template; - - private boolean emitErrors = true; - private boolean parseNullOnError = true; - - public TemplateMethodParser(ProcessorContext context, T template) { - this.template = template; - this.context = context; - } - - public boolean isEmitErrors() { - return emitErrors; - } - - public void setParseNullOnError(boolean nullOnError) { - this.parseNullOnError = nullOnError; - } - - public boolean isParseNullOnError() { - return parseNullOnError; - } - - public void setEmitErrors(boolean emitErrors) { - this.emitErrors = emitErrors; - } - - public ProcessorContext getContext() { - return context; - } - - public TypeSystemData getTypeSystem() { - return template.getTypeSystem(); - } - - public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror); - - public abstract E create(TemplateMethod method); - - public abstract boolean isParsable(ExecutableElement method); - - public Class getAnnotationType() { - return null; - } - - public final List parse(List elements) { - List methods = new ArrayList<>(); - methods.addAll(ElementFilter.methodsIn(elements)); - - List parsedMethods = new ArrayList<>(); - boolean valid = true; - for (ExecutableElement method : methods) { - if (!isParsable(method)) { - continue; - } - - Class annotationType = getAnnotationType(); - AnnotationMirror mirror = null; - if (annotationType != null) { - mirror = Utils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType); - } - - E parsedMethod = parse(method, mirror); - - if (method.getModifiers().contains(Modifier.PRIVATE) && emitErrors) { - parsedMethod.addError("Method must not be private."); - valid = false; - continue; - } - - if (parsedMethod != null) { - parsedMethods.add(parsedMethod); - } else { - valid = false; - } - } - Collections.sort(parsedMethods); - - if (!valid && parseNullOnError) { - return null; - } - return parsedMethods; - } - - private E parse(ExecutableElement method, AnnotationMirror annotation) { - MethodSpec methodSpecification = createSpecification(method, annotation); - if (methodSpecification == null) { - return null; - } - - 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"); - } - - ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); - - ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, false); - if (returnTypeMirror == null) { - if (emitErrors) { - E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList())); - String expectedReturnType = returnTypeSpec.toSignatureString(true); - String actualReturnType = Utils.getSimpleName(method.getReturnType()); - - String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType, - methodSpecification.toSignatureString(method.getSimpleName().toString())); - invalidMethod.addError(message); - return invalidMethod; - } else { - return null; - } - } - - List parameterTypes = new ArrayList<>(); - for (VariableElement var : method.getParameters()) { - parameterTypes.add(var.asType()); - } - - List parameters = parseParameters(methodSpecification, parameterTypes); - if (parameters == null) { - if (isEmitErrors()) { - E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList())); - String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method), - methodSpecification.toSignatureString(method.getSimpleName().toString())); - invalidMethod.addError(message); - return invalidMethod; - } else { - return null; - } - } - - return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters)); - } - - private static String createActualSignature(MethodSpec spec, ExecutableElement method) { - StringBuilder b = new StringBuilder("("); - String sep = ""; - for (TypeMirror implicitType : spec.getImplicitRequiredTypes()) { - b.append(sep); - b.append("implicit " + Utils.getSimpleName(implicitType)); - sep = ", "; - } - for (VariableElement var : method.getParameters()) { - b.append(sep); - b.append(Utils.getSimpleName(var.asType())); - sep = ", "; - } - b.append(")"); - return b.toString(); - } - - private List parseParameters(MethodSpec spec, List parameterTypes) { - List parsedParams = new ArrayList<>(); - ConsumableListIterator types = new ConsumableListIterator<>(parameterTypes); - - // 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, false); - if (optionalParam != null) { - optionals.consume(optionalCount); - types.consume(); - parsedParams.add(optionalParam); - break; - } - optionalCount++; - } - if (oldIndex == types.getIndex()) { - // nothing found anymore skip optional - break; - } - } - - List typesWithImplicit = new ArrayList<>(spec.getImplicitRequiredTypes()); - typesWithImplicit.addAll(types.toList()); - types = new ConsumableListIterator<>(typesWithImplicit); - - 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; - } - break; - } - boolean implicit = types.getIndex() < spec.getImplicitRequiredTypes().size(); - ActualParameter resolvedParameter = matchParameter(required.get(), types.get(), template, specificationParameterIndex, implicit); - if (resolvedParameter == null) { - if (required.get().getCardinality() == Cardinality.MANY) { - required.consume(); - continue; - } - // direct mismatch but required -> error - return null; - } else { - parsedParams.add(resolvedParameter); - types.consume(); - if (required.get().getCardinality() == Cardinality.ONE) { - required.consume(); - specificationParameterIndex = 0; - } else if (required.get().getCardinality() == Cardinality.MANY) { - specificationParameterIndex++; - } - } - } - - if (!types.toList().isEmpty()) { - // additional types -> error - return null; - } - - if (!required.toList().isEmpty() && !spec.isVariableRequiredArguments()) { - // additional specifications -> error - return null; - } - - // success! - return parsedParams; - } - - private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int index, boolean implicit) { - TypeMirror resolvedType = mirror; - if (hasError(resolvedType)) { - resolvedType = context.resolveNotYetCompiledType(mirror, originalTemplate); - } - - if (!specification.matches(resolvedType)) { - return null; - } - - TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType); - if (resolvedTypeData != null) { - return new ActualParameter(specification, resolvedTypeData, index, implicit); - } else { - return new ActualParameter(specification, resolvedType, index, implicit); - } - } - - /* Helper class for parsing. */ - 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 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(); - } - } - - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /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.codegen.processor.template; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.codegen.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 f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +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.codegen.processor.typesystem; - -import com.oracle.truffle.codegen.processor.node.*; -import com.oracle.truffle.codegen.processor.template.*; - -public class GuardData extends TemplateMethod { - - private final SpecializationData specialization; - - public GuardData(TemplateMethod method, SpecializationData specialization) { - super(method); - this.specialization = specialization; - } - - public SpecializationData getSpecialization() { - return specialization; - } - - @Override - public String toString() { - return getMethodName(); - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +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.codegen.processor.typesystem; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.*; -import com.oracle.truffle.codegen.processor.template.*; - -public class GuardParser extends NodeMethodParser { - - private final SpecializationData specialization; - private final String guardName; - - public GuardParser(ProcessorContext context, SpecializationData specialization, String guardName) { - super(context, specialization.getNode()); - this.specialization = specialization; - this.guardName = guardName; - setEmitErrors(false); - setParseNullOnError(false); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null); - spec.setVariableRequiredArguments(true); - spec.getRequired().clear(); - - for (ActualParameter parameter : specialization.getRequiredParameters()) { - ParameterSpec paramSpec = new ParameterSpec(parameter.getLocalName(), parameter.getType(), getNode().getTypeSystem().getGenericType()); - paramSpec.setSignature(true); - spec.addRequired(paramSpec); - } - - return spec; - } - - @Override - protected ParameterSpec createReturnParameterSpec() { - return new ParameterSpec("returnType", getContext().getType(boolean.class)); - } - - @Override - public boolean isParsable(ExecutableElement method) { - return method.getSimpleName().toString().equals(guardName); - } - - @Override - public GuardData create(TemplateMethod method) { - GuardData guard = new GuardData(method, specialization); - /* - * 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 { - newParameters.add(new ActualParameter(specializationParameter.getSpecification(), parameter.getTypeSystemType(), specializationParameter.getIndex(), parameter.isImplicit())); - } - } - guard.setParameters(newParameters); - - return guard; - } - - @Override - public Class getAnnotationType() { - return null; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastData.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +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.codegen.processor.typesystem; - -import com.oracle.truffle.codegen.processor.template.*; - -public class TypeCastData extends TemplateMethod { - - private final TypeData targetType; - private final TypeData sourceType; - - public TypeCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) { - super(method); - this.sourceType = sourceType; - this.targetType = targetType; - } - - public boolean isGeneric() { - return sourceType.isGeneric(); - } - - public TypeData getSourceType() { - return sourceType; - } - - public TypeData getTargetType() { - return targetType; - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +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.codegen.processor.typesystem; - -import java.lang.annotation.*; - -import javax.lang.model.element.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.*; - -class TypeCastParser extends TypeSystemMethodParser { - - public TypeCastParser(ProcessorContext context, TypeSystemData typeSystem) { - super(context, typeSystem); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "as"); - if (targetType == null) { - return null; - } - MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", targetType.getPrimitiveType())); - spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors())); - return spec; - } - - @Override - public TypeCastData create(TemplateMethod method) { - TypeData targetType = findTypeByMethodName(method, "as"); - ActualParameter parameter = method.findParameter("valueValue"); - return new TypeCastData(method, parameter.getTypeSystemType(), targetType); - } - - @Override - public Class getAnnotationType() { - return TypeCast.class; - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckData.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +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.codegen.processor.typesystem; - -import com.oracle.truffle.codegen.processor.template.*; - -public class TypeCheckData extends TemplateMethod { - - private final TypeData checkedType; - private final TypeData valueType; - - public TypeCheckData(TemplateMethod method, TypeData checkedType, TypeData valueType) { - super(method); - this.checkedType = checkedType; - this.valueType = valueType; - } - - public boolean isGeneric() { - return valueType.isGeneric(); - } - - public TypeData getCheckedType() { - return checkedType; - } - - public TypeData getValueType() { - return valueType; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +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.codegen.processor.typesystem; - -import java.lang.annotation.*; - -import javax.lang.model.element.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.*; - -class TypeCheckParser extends TypeSystemMethodParser { - - public TypeCheckParser(ProcessorContext context, TypeSystemData typeSystem) { - super(context, typeSystem); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "is"); - if (targetType == null) { - return null; - } - MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", getContext().getType(boolean.class))); - spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors())); - return spec; - } - - @Override - public TypeCheckData create(TemplateMethod method) { - TypeData checkedType = findTypeByMethodName(method, "is"); - assert checkedType != null; - ActualParameter parameter = method.findParameter("valueValue"); - assert parameter != null; - return new TypeCheckData(method, checkedType, parameter.getTypeSystemType()); - } - - @Override - public Class getAnnotationType() { - return TypeCheck.class; - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +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.codegen.processor.typesystem; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.*; - -public class TypeData extends MessageContainer { - - private final TypeSystemData typeSystem; - private final AnnotationValue annotationValue; - private final TypeMirror primitiveType; - private final TypeMirror boxedType; - - private final List typeCasts = new ArrayList<>(); - private final List typeChecks = new ArrayList<>(); - - public TypeData(TypeSystemData typeSystem, AnnotationValue value, TypeMirror primitiveType, TypeMirror boxedType) { - this.typeSystem = typeSystem; - this.annotationValue = value; - this.primitiveType = primitiveType; - this.boxedType = boxedType; - } - - @Override - public Element getMessageElement() { - return typeSystem.getMessageElement(); - } - - @Override - public AnnotationMirror getMessageAnnotation() { - return typeSystem.getMessageAnnotation(); - } - - @Override - public AnnotationValue getMessageAnnotationValue() { - return annotationValue; - } - - void addTypeCast(TypeCastData typeCast) { - this.typeCasts.add(typeCast); - } - - void addTypeCheck(TypeCheckData typeCheck) { - this.typeChecks.add(typeCheck); - } - - public List getTypeCasts() { - return typeCasts; - } - - public List getTypeChecks() { - return typeChecks; - } - - public TypeSystemData getTypeSystem() { - return typeSystem; - } - - public TypeMirror getPrimitiveType() { - return primitiveType; - } - - public TypeMirror getBoxedType() { - return boxedType; - } - - public boolean isGeneric() { - return Utils.typeEquals(boxedType, getTypeSystem().getGenericType()); - } - - public boolean isVoid() { - if (getTypeSystem().getVoidType() == null) { - return false; - } - return Utils.typeEquals(boxedType, getTypeSystem().getVoidType().getBoxedType()); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "[" + Utils.getSimpleName(primitiveType) + "]"; - } - - public boolean equalsType(TypeData actualTypeData) { - return Utils.typeEquals(boxedType, actualTypeData.boxedType); - } - - public boolean needsCastTo(ProcessorContext context, TypeData targetType) { - if (this.equals(targetType)) { - return false; - } else if (targetType.isGeneric()) { - return false; - } else if (targetType.isVoid()) { - return false; - } else if (Utils.isAssignable(context, getPrimitiveType(), targetType.getPrimitiveType())) { - return false; - } - return true; - } - - public boolean isPrimitive() { - return Utils.isPrimitive(getPrimitiveType()); - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +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.codegen.processor.typesystem; - -import static com.oracle.truffle.codegen.processor.Utils.*; -import static javax.lang.model.element.Modifier.*; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.ast.*; -import com.oracle.truffle.codegen.processor.template.*; - -public class TypeSystemCodeGenerator extends CompilationUnitFactory { - - public TypeSystemCodeGenerator(ProcessorContext context) { - super(context); - } - - public static String isTypeMethodName(TypeData type) { - return "is" + Utils.getTypeId(type.getBoxedType()); - } - - public static String asTypeMethodName(TypeData type) { - return "as" + Utils.getTypeId(type.getBoxedType()); - } - - public static String expectTypeMethodName(TypeData type) { - return "expect" + Utils.getTypeId(type.getBoxedType()); - } - - /** - * Finds the generated singleton field for a TypeSytemData instance. TypeSystemCodeGenerator - * must be applied to the TypeSystemData model before use. - */ - public static VariableElement findSingleton(ProcessorContext context, TypeSystemData typeSystem) { - TypeMirror type = context.findGeneratedClassBySimpleName(TypeClassFactory.typeName(typeSystem), typeSystem); - return Utils.findDeclaredField(type, TypeClassFactory.singletonName(typeSystem.getTemplateType().asType())); - } - - @Override - protected void createChildren(TypeSystemData m) { - add(new TypeClassFactory(context), m); - } - - protected static class TypeClassFactory extends ClassElementFactory { - - private static final String LOCAL_VALUE = "value"; - - public TypeClassFactory(ProcessorContext context) { - super(context); - } - - @Override - public CodeTypeElement create(TypeSystemData typeSystem) { - String name = typeName(typeSystem); - CodeTypeElement clazz = createClass(typeSystem, modifiers(PUBLIC), name, typeSystem.getTemplateType().asType(), false); - - clazz.add(createConstructorUsingFields(modifiers(PROTECTED), clazz)); - CodeVariableElement singleton = createSingleton(clazz); - clazz.add(singleton); - - for (TypeData type : typeSystem.getTypes()) { - if (!type.isGeneric()) { - CodeExecutableElement isType = createIsTypeMethod(type); - if (isType != null) { - clazz.add(isType); - } - CodeExecutableElement asType = createAsTypeMethod(type); - if (asType != null) { - clazz.add(asType); - } - - for (TypeData sourceType : collectExpectSourceTypes(type)) { - CodeExecutableElement expect = createExpectTypeMethod(type, sourceType); - if (expect != null) { - clazz.add(expect); - } - } - } - } - - return clazz; - } - - private static List collectExpectSourceTypes(TypeData type) { - Set sourceTypes = new HashSet<>(); - sourceTypes.add(type.getTypeSystem().getGenericTypeData()); - for (TypeCastData cast : type.getTypeCasts()) { - sourceTypes.add(cast.getSourceType()); - } - for (TypeCheckData cast : type.getTypeChecks()) { - sourceTypes.add(cast.getCheckedType()); - } - return new ArrayList<>(sourceTypes); - } - - private static String typeName(TypeSystemData typeSystem) { - String name = getSimpleName(typeSystem.getTemplateType()); - return name + "Gen"; - } - - private static String singletonName(TypeMirror type) { - return createConstantName(getSimpleName(type)); - } - - private CodeVariableElement createSingleton(CodeTypeElement clazz) { - CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(getModel().getTemplateType().asType())); - field.createInitBuilder().startNew(clazz.asType()).end(); - return field; - } - - private CodeExecutableElement createIsTypeMethod(TypeData type) { - if (!type.getTypeChecks().isEmpty()) { - return null; - } - - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(type)); - method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); - - CodeTreeBuilder body = method.createBuilder(); - body.startReturn().instanceOf(LOCAL_VALUE, type.getBoxedType()).end(); - - return method; - } - - private CodeExecutableElement createAsTypeMethod(TypeData type) { - if (!type.getTypeCasts().isEmpty()) { - return null; - } - - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asTypeMethodName(type)); - method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); - - CodeTreeBuilder body = method.createBuilder(); - body.startAssert().startCall(isTypeMethodName(type)).string(LOCAL_VALUE).end().end(); - body.startReturn().cast(type.getPrimitiveType(), body.create().string(LOCAL_VALUE).getTree()).end(); - - return method; - } - - private CodeExecutableElement createExpectTypeMethod(TypeData expectedType, TypeData sourceType) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), expectedType.getPrimitiveType(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType)); - method.addParameter(new CodeVariableElement(sourceType.getPrimitiveType(), LOCAL_VALUE)); - method.addThrownType(getContext().getTruffleTypes().getUnexpectedValueException()); - - CodeTreeBuilder body = method.createBuilder(); - body.startIf().startCall(null, TypeSystemCodeGenerator.isTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end().startBlock(); - body.startReturn().startCall(null, TypeSystemCodeGenerator.asTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end(); - body.end(); // if-block - body.startThrow().startNew(getContext().getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end(); - - return method; - } - - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +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.codegen.processor.typesystem; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.*; - -public class TypeSystemData extends Template { - - private List types; - private List primitiveTypeMirrors = new ArrayList<>(); - private List boxedTypeMirrors = new ArrayList<>(); - - private TypeMirror genericType; - private TypeData voidType; - - public TypeSystemData(TypeElement templateType, AnnotationMirror annotation) { - super(templateType, null, annotation); - } - - @Override - public TypeSystemData getTypeSystem() { - return this; - } - - void setTypes(List types) { - this.types = types; - if (types != null) { - for (TypeData typeData : types) { - primitiveTypeMirrors.add(typeData.getPrimitiveType()); - boxedTypeMirrors.add(typeData.getBoxedType()); - } - } - } - - void setGenericType(TypeMirror genericType) { - this.genericType = genericType; - } - - void setVoidType(TypeData voidType) { - this.voidType = voidType; - } - - @Override - protected List findChildContainers() { - List sinks = new ArrayList<>(); - if (types != null) { - sinks.addAll(types); - } - return sinks; - } - - public boolean isGeneric(TypeMirror type) { - return Utils.typeEquals(getGenericType(), type); - } - - public TypeData getVoidType() { - return voidType; - } - - public List getBoxedTypeMirrors() { - return boxedTypeMirrors; - } - - public List getPrimitiveTypeMirrors() { - return primitiveTypeMirrors; - } - - public List getTypes() { - return types; - } - - public TypeMirror getGenericType() { - return genericType; - } - - public TypeData getGenericTypeData() { - TypeData result = types.get(types.size() - 1); - assert result.getBoxedType() == genericType; - return result; - } - - public TypeData findType(String simpleName) { - for (TypeData type : types) { - if (Utils.getSimpleName(type.getBoxedType()).equals(simpleName)) { - return type; - } - } - return null; - } - - public TypeData findTypeData(TypeMirror type) { - if (Utils.typeEquals(voidType.getPrimitiveType(), type)) { - return voidType; - } - - int index = findType(type); - if (index == -1) { - return null; - } - return types.get(index); - } - - public int findType(TypeData typeData) { - return findType(typeData.getPrimitiveType()); - } - - public int findType(TypeMirror type) { - for (int i = 0; i < types.size(); i++) { - if (Utils.typeEquals(types.get(i).getPrimitiveType(), type)) { - return i; - } - } - return -1; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "[template = " + Utils.getSimpleName(getTemplateType()) + ", types = " + types + "]"; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +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.codegen.processor.typesystem; - -import javax.lang.model.element.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.*; - -abstract class TypeSystemMethodParser extends TemplateMethodParser { - - public TypeSystemMethodParser(ProcessorContext context, TypeSystemData typeSystem) { - super(context, typeSystem); - } - - @Override - public final boolean isParsable(ExecutableElement method) { - return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; - } - - protected TypeData findTypeByMethodName(String methodName, String prefix) { - String typeName = methodName.substring(prefix.length(), methodName.length()); - TypeData type = getTypeSystem().findType(typeName); - return type; - } - - protected TypeData findTypeByMethodName(TemplateMethod method, String prefix) { - String methodName = method.getMethodName(); - if (!methodName.startsWith(prefix)) { - String annotationName = Utils.getSimpleName(method.getMessageAnnotation().getAnnotationType()); - method.addError("Methods annotated with %s must match the pattern '%s'.", annotationName, String.format("%s${typeName}", prefix)); - return null; - } - String typeName = methodName.substring(prefix.length(), methodName.length()); - TypeData type = getTypeSystem().findType(typeName); - if (type == null) { - String annotationName = TypeSystem.class.getSimpleName(); - method.addError("Type '%s' is not declared in this @%s.", typeName, annotationName); - return null; - } - - return type; - } - -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java Mon Jul 01 20:32:20 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,277 +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.codegen.processor.typesystem; - -import static com.oracle.truffle.codegen.processor.Utils.*; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.*; - -public class TypeSystemParser extends TemplateParser { - - public static final List> ANNOTATIONS = Arrays.asList(TypeSystem.class); - - public TypeSystemParser(ProcessorContext c) { - super(c); - } - - @Override - public Class getAnnotationType() { - return TypeSystem.class; - } - - @Override - protected TypeSystemData parse(Element element, AnnotationMirror mirror) { - TypeElement templateType = (TypeElement) element; - AnnotationMirror templateTypeAnnotation = mirror; - TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation); - - // annotation type on class path!? - TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName()); - if (annotationTypeElement == null) { - typeSystem.addError("Required class %s is not on the classpath.", getAnnotationType().getName()); - } - if (templateType.getModifiers().contains(Modifier.PRIVATE)) { - typeSystem.addError("A @%s must have at least package protected visibility.", getAnnotationType().getName()); - } - - if (templateType.getModifiers().contains(Modifier.FINAL)) { - typeSystem.addError("The @%s must not be final.", getAnnotationType().getName()); - } - if (typeSystem.hasErrors()) { - return typeSystem; - } - - typeSystem.setTypes(parseTypes(typeSystem)); - if (typeSystem.getTypes() == null) { - return typeSystem; - } - - TypeMirror genericType = context.getType(Object.class); - TypeData voidType = new TypeData(typeSystem, null, context.getType(void.class), context.getType(Void.class)); - - typeSystem.setGenericType(genericType); - typeSystem.setVoidType(voidType); - - verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class); - - List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType)); - - List casts = new TypeCastParser(context, typeSystem).parse(elements); - List checks = new TypeCheckParser(context, typeSystem).parse(elements); - - if (casts == null || checks == null) { - return typeSystem; - } - - for (TypeCheckData check : checks) { - check.getCheckedType().addTypeCheck(check); - } - - for (TypeCastData cast : casts) { - cast.getTargetType().addTypeCast(cast); - } - - verifyGenericTypeChecksAndCasts(typeSystem); - verifyMethodSignatures(typeSystem); - verifyNamesUnique(typeSystem); - - return typeSystem; - } - - private static void verifyGenericTypeChecksAndCasts(TypeSystemData typeSystem) { - for (TypeData type : typeSystem.getTypes()) { - if (!type.getTypeChecks().isEmpty()) { - boolean hasGeneric = false; - for (TypeCheckData typeCheck : type.getTypeChecks()) { - if (typeCheck.isGeneric()) { - hasGeneric = true; - break; - } - } - if (!hasGeneric) { - type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.", - TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(), - Object.class.getSimpleName()); - } - } - if (!type.getTypeCasts().isEmpty()) { - boolean hasGeneric = false; - for (TypeCastData typeCast : type.getTypeCasts()) { - if (typeCast.isGeneric()) { - hasGeneric = true; - break; - } - } - if (!hasGeneric) { - type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.", - TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(), - Object.class.getSimpleName()); - } - } - } - } - - private List parseTypes(TypeSystemData typeSystem) { - List types = new ArrayList<>(); - List typeMirrors = Utils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value"); - if (typeMirrors.isEmpty()) { - typeSystem.addError("At least one type must be defined."); - return types; - } - - final AnnotationValue annotationValue = Utils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "value"); - final TypeMirror objectType = context.getType(Object.class); - - for (TypeMirror primitiveType : typeMirrors) { - TypeMirror boxedType = Utils.boxType(context, primitiveType); - TypeData typeData = new TypeData(typeSystem, annotationValue, primitiveType, boxedType); - - if (isPrimitiveWrapper(primitiveType)) { - typeData.addError("Types must not contain primitive wrapper types."); - } - - if (Utils.typeEquals(boxedType, objectType)) { - typeData.addError("Types must not contain the generic type java.lang.Object."); - } - - types.add(typeData); - } - - verifyTypeOrder(types); - - types.add(new TypeData(typeSystem, annotationValue, objectType, objectType)); - - return types; - } - - private static void verifyTypeOrder(List types) { - Map> invalidTypes = new HashMap<>(); - - for (int i = types.size() - 1; i >= 0; i--) { - TypeData typeData = types.get(i); - TypeMirror type = typeData.getBoxedType(); - if (invalidTypes.containsKey(Utils.getQualifiedName(type))) { - typeData.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(Utils.getQualifiedName(type)), Utils.getQualifiedName(type)); - } - List nextInvalidTypes = Utils.getQualifiedSuperTypeNames(Utils.fromTypeMirror(type)); - nextInvalidTypes.add(getQualifiedName(type)); - - for (String qualifiedName : nextInvalidTypes) { - List inheritedTypes = invalidTypes.get(qualifiedName); - if (inheritedTypes == null) { - inheritedTypes = new ArrayList<>(); - invalidTypes.put(qualifiedName, inheritedTypes); - } - inheritedTypes.add(Utils.getQualifiedName(typeData.getBoxedType())); - } - } - } - - private boolean isPrimitiveWrapper(TypeMirror type) { - Types types = context.getEnvironment().getTypeUtils(); - for (TypeKind kind : TypeKind.values()) { - if (!kind.isPrimitive()) { - continue; - } - if (Utils.typeEquals(type, types.boxedClass(types.getPrimitiveType(kind)).asType())) { - return true; - } - } - return false; - } - - private void verifyMethodSignatures(TypeSystemData typeSystem) { - Set generatedIsMethodNames = new HashSet<>(); - Set generatedAsMethodNames = new HashSet<>(); - Set generatedExpectMethodNames = new HashSet<>(); - - for (TypeData typeData : typeSystem.getTypes()) { - generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData)); - generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData)); - generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData)); - } - - List methods = ElementFilter.methodsIn(typeSystem.getTemplateType().getEnclosedElements()); - for (ExecutableElement method : methods) { - if (method.getModifiers().contains(Modifier.PRIVATE)) { - // will not conflict overridden methods - continue; - } else if (method.getParameters().size() != 1) { - continue; - } - String methodName = method.getSimpleName().toString(); - if (generatedIsMethodNames.contains(methodName)) { - verifyIsMethod(typeSystem, method); - } else if (generatedAsMethodNames.contains(methodName)) { - verifyAsMethod(typeSystem, method); - } else if (generatedExpectMethodNames.contains(methodName)) { - verifyExpectMethod(typeSystem); - } - } - } - - private boolean verifyIsMethod(TypeSystemData typeSystem, ExecutableElement method) { - AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCheck.class); - if (mirror == null) { - typeSystem.addError("Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName()); - return false; - } - return true; - } - - private boolean verifyAsMethod(TypeSystemData typeSystem, ExecutableElement method) { - AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCast.class); - if (mirror == null) { - typeSystem.addError("Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName()); - return false; - } - return true; - } - - private static boolean verifyExpectMethod(TypeSystemData typeSystem) { - typeSystem.addError("Method starting with the pattern expect${typeName} must not be declared manually."); - return false; - } - - private static void verifyNamesUnique(TypeSystemData typeSystem) { - List types = typeSystem.getTypes(); - for (int i = 0; i < types.size(); i++) { - for (int j = i + 1; j < types.size(); j++) { - String name1 = Utils.getSimpleName(types.get(i).getBoxedType()); - String name2 = Utils.getSimpleName(types.get(j).getBoxedType()); - if (name1.equalsIgnoreCase(name2)) { - typeSystem.addError("Two types result in the same name: %s, %s.", name1, name2); - } - } - } - } -} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/META-INF/services/javax.annotation.processing.Processor --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/META-INF/services/javax.annotation.processing.Processor Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,1 @@ +com.oracle.truffle.dsl.processor.TruffleProcessor diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,103 @@ +/* + * 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; + +import java.lang.annotation.*; +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.tools.Diagnostic.Kind; + +import com.oracle.truffle.dsl.processor.template.*; + +/** + * THIS IS NOT PUBLIC API. + */ +public abstract class AbstractParser { + + protected final ProcessorContext context; + protected final ProcessingEnvironment processingEnv; + protected RoundEnvironment roundEnv; + + protected final Log log; + + public AbstractParser(ProcessorContext c) { + this.context = c; + this.processingEnv = c.getEnvironment(); + this.log = c.getLog(); + } + + public final M parse(RoundEnvironment env, Element element) { + this.roundEnv = env; + M model = null; + try { + AnnotationMirror mirror = null; + if (getAnnotationType() != null) { + mirror = Utils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType()); + } + + if (!context.getTruffleTypes().verify(context, element, mirror)) { + return null; + } + model = parse(element, mirror); + if (model == null) { + return null; + } + + model.emitMessages((TypeElement) element, log); + return filterErrorElements(model); + } catch (CompileErrorException e) { + log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage()); + return null; + } finally { + this.roundEnv = null; + } + } + + protected M filterErrorElements(M model) { + return model.hasErrors() ? null : model; + } + + protected abstract M parse(Element element, AnnotationMirror mirror); + + public abstract Class getAnnotationType(); + + public boolean isDelegateToRootDeclaredType() { + return false; + } + + public List> getAllAnnotationTypes() { + List> list = new ArrayList<>(); + if (getAnnotationType() != null) { + list.add(getAnnotationType()); + } + list.addAll(getTypeDelegatedAnnotationTypes()); + return list; + } + + public List> getTypeDelegatedAnnotationTypes() { + return Collections.emptyList(); + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,132 @@ +/* + * 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; + +import java.io.*; +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.tools.*; + +import com.oracle.truffle.dsl.processor.ast.*; +import com.oracle.truffle.dsl.processor.codewriter.*; +import com.oracle.truffle.dsl.processor.compiler.*; +import com.oracle.truffle.dsl.processor.template.*; + +/** + * THIS IS NOT PUBLIC API. + */ +class AnnotationProcessor { + + private final AbstractParser parser; + private final CompilationUnitFactory factory; + private final ProcessorContext context; + + private final Set processedElements = new HashSet<>(); + + public AnnotationProcessor(ProcessorContext context, AbstractParser parser, CompilationUnitFactory factory) { + this.context = context; + this.parser = parser; + this.factory = factory; + } + + public AbstractParser getParser() { + return parser; + } + + public ProcessorContext getContext() { + return context; + } + + @SuppressWarnings({"unchecked"}) + public void process(RoundEnvironment env, Element element, boolean callback) { + + // since it is not guaranteed to be called only once by the compiler + // we check for already processed elements to avoid errors when writing files. + if (!callback && element instanceof TypeElement) { + String qualifiedName = Utils.getQualifiedName((TypeElement) element); + if (processedElements.contains(qualifiedName)) { + return; + } + processedElements.add(qualifiedName); + } + + TypeElement type = (TypeElement) element; + + M model = (M) context.getTemplate(type.asType(), false); + boolean firstRun = !context.containsTemplate(type); + + if (firstRun || !callback) { + context.registerTemplate(type, null); + model = parser.parse(env, element); + context.registerTemplate(type, model); + + if (model != null) { + CodeCompilationUnit unit = factory.process(null, model); + unit.setGeneratorAnnotationMirror(model.getTemplateTypeAnnotation()); + unit.setGeneratorElement(model.getTemplateType()); + + DeclaredType overrideType = (DeclaredType) context.getType(Override.class); + DeclaredType unusedType = (DeclaredType) context.getType(SuppressWarnings.class); + unit.accept(new GenerateOverrideVisitor(overrideType), null); + unit.accept(new FixWarningsVisitor(context, unusedType, overrideType), null); + + if (!callback) { + unit.accept(new CodeWriter(context.getEnvironment(), element), null); + } + } + } + } + + private static class CodeWriter extends AbstractCodeWriter { + + private final Element orignalElement; + private final ProcessingEnvironment env; + + public CodeWriter(ProcessingEnvironment env, Element originalElement) { + this.env = env; + this.orignalElement = originalElement; + } + + @Override + protected Writer createWriter(CodeTypeElement clazz) throws IOException { + JavaFileObject jfo = env.getFiler().createSourceFile(clazz.getQualifiedName(), orignalElement); + return jfo.openWriter(); + } + + @Override + protected void writeHeader() { + if (env == null) { + return; + } + String comment = CompilerFactory.getCompiler(orignalElement).getHeaderComment(env, orignalElement); + if (comment != null) { + writeLn(comment); + } + } + + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/CompileErrorException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/CompileErrorException.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor; + +public class CompileErrorException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public CompileErrorException(String message) { + super(message); + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,61 @@ +/* + * 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; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.tools.Diagnostic.Kind; + +import com.oracle.truffle.dsl.processor.ast.*; + +/** + * THIS IS NOT PUBLIC API. + */ +public class Log { + + public static final boolean DEBUG = false; + + private final ProcessingEnvironment processingEnv; + + public Log(ProcessingEnvironment env) { + this.processingEnv = env; + } + + public void message(Kind kind, Element element, AnnotationMirror mirror, AnnotationValue value, String format, Object... args) { + AnnotationMirror usedMirror = mirror; + Element usedElement = element; + AnnotationValue usedValue = value; + String message = String.format(format, args); + + if (element instanceof GeneratedElement) { + usedMirror = ((GeneratedElement) element).getGeneratorAnnotationMirror(); + usedElement = ((GeneratedElement) element).getGeneratorElement(); + usedValue = null; + if (usedElement != null) { + message = String.format("Element %s: %s", element, message); + } + } + processingEnv.getMessager().printMessage(kind, message, usedElement, usedMirror, usedValue); + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,212 @@ +/* + * 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; + +import static com.oracle.truffle.dsl.processor.Utils.*; + +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.dsl.processor.ast.*; +import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.*; +import com.oracle.truffle.dsl.processor.template.*; + +/** + * THIS IS NOT PUBLIC API. + */ +public class ProcessorContext { + + private final ProcessingEnvironment environment; + + private final Map models = new HashMap<>(); + private final Map> generatedClasses = new HashMap<>(); + + private final ProcessCallback callback; + private final Log log; + private final TruffleTypes truffleTypes; + + public ProcessorContext(ProcessingEnvironment env, ProcessCallback callback) { + this.environment = env; + this.callback = callback; + this.log = new Log(environment); + this.truffleTypes = new TruffleTypes(this); + } + + public TruffleTypes getTruffleTypes() { + return truffleTypes; + } + + public Log getLog() { + return log; + } + + public ProcessingEnvironment getEnvironment() { + return environment; + } + + public boolean containsTemplate(TypeElement element) { + return models.containsKey(Utils.getQualifiedName(element)); + } + + public void registerTemplate(TypeElement element, Template model) { + models.put(Utils.getQualifiedName(element), model); + } + + public void registerType(TypeElement templateType, TypeMirror generatedTypeMirror) { + String templateQualifiedName = getQualifiedName(templateType); + Map simpleNameToType = generatedClasses.get(templateQualifiedName); + if (simpleNameToType == null) { + simpleNameToType = new HashMap<>(); + generatedClasses.put(templateQualifiedName, simpleNameToType); + } + String generatedSimpleName = getSimpleName(generatedTypeMirror); + simpleNameToType.put(generatedSimpleName, generatedTypeMirror); + } + + public Template getTemplate(TypeMirror templateTypeMirror, boolean invokeCallback) { + String qualifiedName = Utils.getQualifiedName(templateTypeMirror); + Template model = models.get(qualifiedName); + if (model == null && invokeCallback) { + callback.callback(Utils.fromTypeMirror(templateTypeMirror)); + model = models.get(qualifiedName); + } + return model; + } + + public TypeMirror resolveNotYetCompiledType(TypeMirror mirror, Template templateHint) { + TypeMirror resolvedType = null; + if (mirror.getKind() == TypeKind.ARRAY) { + TypeMirror originalComponentType = ((ArrayType) mirror).getComponentType(); + TypeMirror resolvedComponent = resolveNotYetCompiledType(originalComponentType, templateHint); + if (resolvedComponent != originalComponentType) { + return new ArrayCodeTypeMirror(resolvedComponent); + } + } + + if (mirror.getKind() == TypeKind.ERROR) { + Element element = ((ErrorType) mirror).asElement(); + ElementKind kind = element.getKind(); + if (kind == ElementKind.CLASS || kind == ElementKind.PARAMETER || kind == ElementKind.ENUM) { + String simpleName = element.getSimpleName().toString(); + resolvedType = findGeneratedClassBySimpleName(simpleName, templateHint); + } + } else { + resolvedType = mirror; + } + + return resolvedType; + } + + public TypeMirror findGeneratedClassBySimpleName(String simpleName, Template templateHint) { + if (templateHint == null) { + // search all + for (String qualifiedTemplateName : generatedClasses.keySet()) { + Map mirrors = generatedClasses.get(qualifiedTemplateName); + if (mirrors.get(simpleName) != null) { + return mirrors.get(simpleName); + } + } + return null; + } else { + String templateQualifiedName = getQualifiedName(templateHint.getTemplateType()); + Map simpleNameToType = generatedClasses.get(templateQualifiedName); + if (simpleNameToType == null) { + return null; + } + return simpleNameToType.get(simpleName); + } + } + + public TypeMirror getType(String className) { + TypeElement element = environment.getElementUtils().getTypeElement(className); + if (element != null) { + return element.asType(); + } + return null; + } + + public TypeMirror getType(Class element) { + TypeMirror mirror; + if (element.isPrimitive()) { + if (element == boolean.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.BOOLEAN); + } else if (element == byte.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.BYTE); + } else if (element == short.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.SHORT); + } else if (element == char.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.CHAR); + } else if (element == int.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.INT); + } else if (element == long.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.LONG); + } else if (element == float.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.FLOAT); + } else if (element == double.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.DOUBLE); + } else if (element == void.class) { + mirror = environment.getTypeUtils().getNoType(TypeKind.VOID); + } else { + assert false; + return null; + } + } else { + TypeElement typeElement = environment.getElementUtils().getTypeElement(element.getCanonicalName()); + mirror = typeElement.asType(); + } + return mirror; + } + + public interface ProcessCallback { + + void callback(TypeElement template); + + } + + public TypeMirror reloadTypeElement(TypeElement type) { + return getType(type.getQualifiedName().toString()); + } + + public TypeMirror reloadType(TypeMirror type) { + if (type instanceof CodeTypeMirror) { + return type; + } else if (type.getKind().isPrimitive()) { + return type; + } + Types types = getEnvironment().getTypeUtils(); + + switch (type.getKind()) { + case ARRAY: + return types.getArrayType(reloadType(((ArrayType) type).getComponentType())); + case WILDCARD: + return types.getWildcardType(((WildcardType) type).getExtendsBound(), ((WildcardType) type).getSuperBound()); + case DECLARED: + return reloadTypeElement((TypeElement) (((DeclaredType) type).asElement())); + } + return type; + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,150 @@ +/* + * 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; + +import java.lang.annotation.*; +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.tools.Diagnostic.*; + +import com.oracle.truffle.dsl.processor.ProcessorContext.*; +import com.oracle.truffle.dsl.processor.node.*; +import com.oracle.truffle.dsl.processor.typesystem.*; + +/** + * THIS IS NOT PUBLIC API. + */ +// @SupportedAnnotationTypes({"com.oracle.truffle.codegen.Operation", +// "com.oracle.truffle.codegen.TypeLattice"}) +@SupportedSourceVersion(SourceVersion.RELEASE_7) +public class TruffleProcessor extends AbstractProcessor implements ProcessCallback { + + private ProcessorContext context; + private List> generators; + + private RoundEnvironment round; + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (!roundEnv.processingOver()) { + processImpl(roundEnv); + } + return false; + } + + private void processImpl(RoundEnvironment env) { + this.round = env; + // TODO run verifications that other annotations are not processed out of scope of the + // operation or typelattice. + try { + for (AnnotationProcessor generator : getGenerators()) { + AbstractParser parser = generator.getParser(); + if (parser.getAnnotationType() != null) { + for (Element e : env.getElementsAnnotatedWith(parser.getAnnotationType())) { + processElement(env, generator, e, false); + } + } + + for (Class annotationType : parser.getTypeDelegatedAnnotationTypes()) { + for (Element e : env.getElementsAnnotatedWith(annotationType)) { + TypeElement processedType; + if (parser.isDelegateToRootDeclaredType()) { + processedType = Utils.findRootEnclosingType(e); + } else { + processedType = Utils.findNearestEnclosingType(e); + } + processElement(env, generator, processedType, false); + } + } + + } + } finally { + this.round = null; + } + } + + private static void processElement(RoundEnvironment env, AnnotationProcessor generator, Element e, boolean callback) { + try { + generator.process(env, e, callback); + } catch (Throwable e1) { + handleThrowable(generator, e1, e); + } + } + + private static void handleThrowable(AnnotationProcessor generator, Throwable t, Element e) { + String message = "Uncaught error in " + generator.getClass().getSimpleName() + " while processing " + e; + generator.getContext().getLog().message(Kind.ERROR, e, null, null, message + ": " + Utils.printException(t)); + } + + @SuppressWarnings("unchecked") + @Override + public void callback(TypeElement template) { + for (AnnotationProcessor generator : generators) { + Class annotationType = generator.getParser().getAnnotationType(); + if (annotationType != null) { + Annotation annotation = template.getAnnotation(annotationType); + if (annotation != null) { + processElement(round, generator, template, true); + } + } + } + } + + @Override + public Set getSupportedAnnotationTypes() { + Set annotations = new HashSet<>(); + List> annotationsTypes = new ArrayList<>(); + annotationsTypes.addAll(NodeParser.ANNOTATIONS); + annotationsTypes.addAll(TypeSystemParser.ANNOTATIONS); + for (Class type : annotationsTypes) { + annotations.add(type.getCanonicalName()); + } + return annotations; + } + + private List> getGenerators() { + if (generators == null && processingEnv != null) { + generators = new ArrayList<>(); + generators.add(new AnnotationProcessor<>(getContext(), new TypeSystemParser(getContext()), new TypeSystemCodeGenerator(getContext()))); + generators.add(new AnnotationProcessor<>(getContext(), new NodeParser(getContext()), new NodeCodeGenerator(getContext()))); + } + return generators; + } + + private ProcessorContext getContext() { + if (context == null) { + context = new ProcessorContext(processingEnv, this); + } + return context; + } + + @Override + public synchronized void init(ProcessingEnvironment env) { + this.processingEnv = env; + super.init(env); + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,139 @@ +/* + * 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; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.tools.Diagnostic.Kind; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.Node.Child; +import com.oracle.truffle.api.nodes.Node.Children; + +/** + * THIS IS NOT PUBLIC API. + */ +public final class TruffleTypes { + + private final TypeMirror node; + private final TypeMirror nodeArray; + private final TypeMirror unexpectedValueException; + private final TypeMirror frame; + private final TypeMirror assumption; + private final TypeMirror invalidAssumption; + private final DeclaredType childAnnotation; + private final DeclaredType childrenAnnotation; + private final DeclaredType nodeInfoAnnotation; + private final DeclaredType nodeInfoKind; + private final TypeMirror compilerDirectives; + private final TypeMirror compilerAsserts; + + private final List errors = new ArrayList<>(); + + public TruffleTypes(ProcessorContext context) { + node = getRequired(context, Node.class); + nodeArray = context.getEnvironment().getTypeUtils().getArrayType(node); + unexpectedValueException = getRequired(context, UnexpectedResultException.class); + frame = getRequired(context, VirtualFrame.class); + childAnnotation = getRequired(context, Child.class); + childrenAnnotation = getRequired(context, Children.class); + compilerDirectives = getRequired(context, CompilerDirectives.class); + compilerAsserts = getRequired(context, CompilerAsserts.class); + assumption = getRequired(context, Assumption.class); + invalidAssumption = getRequired(context, InvalidAssumptionException.class); + nodeInfoAnnotation = getRequired(context, NodeInfo.class); + nodeInfoKind = getRequired(context, NodeInfo.Kind.class); + } + + public DeclaredType getNodeInfoAnnotation() { + return nodeInfoAnnotation; + } + + public boolean verify(ProcessorContext context, Element element, AnnotationMirror mirror) { + if (errors.isEmpty()) { + return true; + } + + for (String error : errors) { + context.getLog().message(Kind.ERROR, element, mirror, null, error); + } + + return false; + } + + public DeclaredType getNodeInfoKind() { + return nodeInfoKind; + } + + private DeclaredType getRequired(ProcessorContext context, Class clazz) { + TypeMirror type = context.getType(clazz); + if (type == null) { + errors.add(String.format("Could not find required type: %s", clazz.getSimpleName())); + } + return (DeclaredType) type; + } + + public TypeMirror getInvalidAssumption() { + return invalidAssumption; + } + + public TypeMirror getAssumption() { + return assumption; + } + + public TypeMirror getCompilerDirectives() { + return compilerDirectives; + } + + public TypeMirror getNode() { + return node; + } + + public TypeMirror getNodeArray() { + return nodeArray; + } + + public TypeMirror getFrame() { + return frame; + } + + public TypeMirror getUnexpectedValueException() { + return unexpectedValueException; + } + + public DeclaredType getChildAnnotation() { + return childAnnotation; + } + + public DeclaredType getChildrenAnnotation() { + return childrenAnnotation; + } + + public TypeMirror getCompilerAsserts() { + return compilerAsserts; + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,930 @@ +/* + * 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; + +import java.io.*; +import java.lang.annotation.*; +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.dsl.processor.ast.*; +import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.*; +import com.oracle.truffle.dsl.processor.compiler.*; + +/** + * THIS IS NOT PUBLIC API. + */ +public class Utils { + + public static ExecutableElement findExecutableElement(DeclaredType type, String name) { + List elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements()); + for (ExecutableElement executableElement : elements) { + if (executableElement.getSimpleName().toString().equals(name)) { + return executableElement; + } + } + return null; + } + + public static VariableElement findVariableElement(DeclaredType type, String name) { + List elements = ElementFilter.fieldsIn(type.asElement().getEnclosedElements()); + for (VariableElement variableElement : elements) { + if (variableElement.getSimpleName().toString().equals(name)) { + return variableElement; + } + } + return null; + } + + public static String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { + if (method instanceof CodeExecutableElement) { + return ((CodeExecutableElement) method).getBody(); + } else { + return CompilerFactory.getCompiler(method).getMethodBody(env, method); + } + } + + public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) { + TypeMirror boxedType = primitiveType; + if (boxedType.getKind().isPrimitive()) { + boxedType = context.getEnvironment().getTypeUtils().boxedClass((PrimitiveType) boxedType).asType(); + } + return boxedType; + } + + public static List asTypeMirrors(List elements) { + List types = new ArrayList<>(elements.size()); + for (Element element : elements) { + types.add(element.asType()); + } + return types; + } + + public static DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) { + return new DeclaredCodeTypeMirror(typeElem, Arrays.asList(typeArgs)); + } + + public static List collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element, + Class annotationClass) { + List result = new ArrayList<>(); + if (markerAnnotation != null) { + result.addAll(Utils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName)); + } + AnnotationMirror explicit = Utils.findAnnotationMirror(context.getEnvironment(), element, annotationClass); + if (explicit != null) { + result.add(explicit); + } + return result; + } + + public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror[] types) { + if (types.length == 0) { + return context.getType(Object.class); + } + TypeMirror prev = types[0]; + for (int i = 1; i < types.length; i++) { + prev = getCommonSuperType(context, prev, types[i]); + } + return prev; + } + + public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror type1, TypeMirror type2) { + if (typeEquals(type1, type2)) { + return type1; + } + TypeElement element1 = fromTypeMirror(type1); + TypeElement element2 = fromTypeMirror(type2); + if (element1 == null || element2 == null) { + return context.getType(Object.class); + } + + List element1Types = getDirectSuperTypes(element1); + element1Types.add(0, element1); + List element2Types = getDirectSuperTypes(element2); + element2Types.add(0, element2); + + for (TypeElement superType1 : element1Types) { + for (TypeElement superType2 : element2Types) { + if (typeEquals(superType1.asType(), superType2.asType())) { + return superType2.asType(); + } + } + } + return context.getType(Object.class); + } + + public static String getReadableSignature(ExecutableElement method) { + // TODO toString does not guarantee a good signature + return method.toString(); + } + + public static boolean hasError(TypeMirror mirror) { + switch (mirror.getKind()) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case SHORT: + case LONG: + case DECLARED: + case VOID: + case TYPEVAR: + return false; + case ARRAY: + return hasError(((ArrayType) mirror).getComponentType()); + case ERROR: + return true; + default: + throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); + } + } + + public static boolean isAssignable(ProcessorContext context, TypeMirror from, TypeMirror to) { + if (!(from instanceof CodeTypeMirror) && !(to instanceof CodeTypeMirror)) { + return context.getEnvironment().getTypeUtils().isAssignable(context.reloadType(from), context.reloadType(to)); + } else { + return isAssignableImpl(context, from, to); + } + } + + private static boolean isAssignableImpl(ProcessorContext context, TypeMirror from, TypeMirror to) { + // JLS 5.1.1 identity conversion + if (Utils.typeEquals(from, to)) { + return true; + } + + // JLS 5.1.2 widening primitives + if (Utils.isPrimitive(from) && Utils.isPrimitive(to)) { + TypeKind fromKind = from.getKind(); + TypeKind toKind = to.getKind(); + switch (fromKind) { + case BYTE: + switch (toKind) { + case SHORT: + case INT: + case LONG: + case FLOAT: + case DOUBLE: + return true; + } + break; + case SHORT: + switch (toKind) { + case INT: + case LONG: + case FLOAT: + case DOUBLE: + return true; + } + break; + case CHAR: + switch (toKind) { + case INT: + case LONG: + case FLOAT: + case DOUBLE: + return true; + } + break; + case INT: + switch (toKind) { + case LONG: + case FLOAT: + case DOUBLE: + return true; + } + break; + case LONG: + switch (toKind) { + case FLOAT: + case DOUBLE: + return true; + } + break; + case FLOAT: + switch (toKind) { + case DOUBLE: + return true; + } + break; + + } + return false; + } else if (Utils.isPrimitive(from) || Utils.isPrimitive(to)) { + return false; + } + + if (from instanceof ArrayType && to instanceof ArrayType) { + return isAssignable(context, ((ArrayType) from).getComponentType(), ((ArrayType) to).getComponentType()); + } + + TypeElement fromType = Utils.fromTypeMirror(from); + TypeElement toType = Utils.fromTypeMirror(to); + if (fromType == null || toType == null) { + return false; + } + // JLS 5.1.6 narrowing reference conversion + + List superTypes = Utils.getSuperTypes(fromType); + for (TypeElement superType : superTypes) { + if (Utils.typeEquals(superType.asType(), to)) { + return true; + } + } + + // TODO more spec + return false; + } + + public static Set modifiers(Modifier... modifier) { + return new LinkedHashSet<>(Arrays.asList(modifier)); + } + + public static String getTypeId(TypeMirror mirror) { + switch (mirror.getKind()) { + case BOOLEAN: + return "Boolean"; + case BYTE: + return "Byte"; + case CHAR: + return "Char"; + case DOUBLE: + return "Double"; + case FLOAT: + return "Float"; + case SHORT: + return "Short"; + case INT: + return "Int"; + case LONG: + return "Long"; + case DECLARED: + return ((DeclaredType) mirror).asElement().getSimpleName().toString(); + case ARRAY: + return getTypeId(((ArrayType) mirror).getComponentType()) + "Array"; + case VOID: + return "Void"; + case WILDCARD: + StringBuilder b = new StringBuilder(); + WildcardType type = (WildcardType) mirror; + if (type.getExtendsBound() != null) { + b.append("Extends").append(getTypeId(type.getExtendsBound())); + } else if (type.getSuperBound() != null) { + b.append("Super").append(getTypeId(type.getExtendsBound())); + } + return b.toString(); + case TYPEVAR: + return "Any"; + case ERROR: + throw new CompileErrorException("Type error " + mirror); + default: + throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); + } + } + + public static String getSimpleName(TypeElement element) { + return getSimpleName(element.asType()); + } + + public static String getSimpleName(TypeMirror mirror) { + switch (mirror.getKind()) { + case BOOLEAN: + return "boolean"; + case BYTE: + return "byte"; + case CHAR: + return "char"; + case DOUBLE: + return "double"; + case FLOAT: + return "float"; + case SHORT: + return "short"; + case INT: + return "int"; + case LONG: + return "long"; + case DECLARED: + return getDeclaredName((DeclaredType) mirror); + case ARRAY: + return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]"; + case VOID: + return "void"; + case WILDCARD: + return getWildcardName((WildcardType) mirror); + case TYPEVAR: + return "?"; + case ERROR: + throw new CompileErrorException("Type error " + mirror); + default: + throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); + } + } + + private static String getWildcardName(WildcardType type) { + StringBuilder b = new StringBuilder(); + if (type.getExtendsBound() != null) { + b.append("? extends ").append(getSimpleName(type.getExtendsBound())); + } else if (type.getSuperBound() != null) { + b.append("? super ").append(getSimpleName(type.getExtendsBound())); + } + return b.toString(); + } + + private static String getDeclaredName(DeclaredType element) { + String simpleName = element.asElement().getSimpleName().toString(); + + if (element.getTypeArguments().size() == 0) { + return simpleName; + } + + StringBuilder b = new StringBuilder(simpleName); + b.append("<"); + if (element.getTypeArguments().size() > 0) { + for (int i = 0; i < element.getTypeArguments().size(); i++) { + b.append(getSimpleName(element.getTypeArguments().get(i))); + if (i < element.getTypeArguments().size() - 1) { + b.append(", "); + } + } + } + b.append(">"); + return b.toString(); + } + + public static String getQualifiedName(TypeElement element) { + return element.getQualifiedName().toString(); + } + + public static String getQualifiedName(TypeMirror mirror) { + switch (mirror.getKind()) { + case BOOLEAN: + return "boolean"; + case BYTE: + return "byte"; + case CHAR: + return "char"; + case DOUBLE: + return "double"; + case SHORT: + return "short"; + case FLOAT: + return "float"; + case INT: + return "int"; + case LONG: + return "long"; + case DECLARED: + return getQualifiedName(fromTypeMirror(mirror)); + case ARRAY: + return getQualifiedName(((ArrayType) mirror).getComponentType()); + case VOID: + return "void"; + case TYPEVAR: + return getSimpleName(mirror); + case ERROR: + throw new CompileErrorException("Type error " + mirror); + case NONE: + return "$none"; + default: + throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror); + } + } + + public static boolean isVoid(TypeMirror mirror) { + return mirror.getKind() == TypeKind.VOID; + } + + public static boolean isPrimitive(TypeMirror mirror) { + return mirror.getKind().isPrimitive(); + } + + public static boolean isPrimitiveOrVoid(TypeMirror mirror) { + return isPrimitive(mirror) || isVoid(mirror); + } + + public static List getQualifiedSuperTypeNames(TypeElement element) { + List types = getSuperTypes(element); + List qualifiedNames = new ArrayList<>(); + for (TypeElement type : types) { + qualifiedNames.add(getQualifiedName(type)); + } + return qualifiedNames; + } + + public static List getDeclaredTypes(TypeElement element) { + return ElementFilter.typesIn(element.getEnclosedElements()); + } + + public static VariableElement findDeclaredField(TypeMirror type, String singletonName) { + List elements = ElementFilter.fieldsIn(fromTypeMirror(type).getEnclosedElements()); + for (VariableElement var : elements) { + if (var.getSimpleName().toString().equals(singletonName)) { + return var; + } + } + return null; + } + + public static TypeElement findRootEnclosingType(Element element) { + List elements = getElementHierarchy(element); + + for (int i = elements.size() - 1; i >= 0; i--) { + if (elements.get(i).getKind().isClass()) { + return (TypeElement) elements.get(i); + } + } + + return null; + } + + public static List getElementHierarchy(Element e) { + List elements = new ArrayList<>(); + elements.add(e); + + Element enclosing = e.getEnclosingElement(); + while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) { + elements.add(enclosing); + enclosing = enclosing.getEnclosingElement(); + } + if (enclosing != null) { + elements.add(enclosing); + } + return elements; + } + + public static TypeElement findNearestEnclosingType(Element element) { + List elements = getElementHierarchy(element); + for (Element e : elements) { + if (e.getKind().isClass()) { + return (TypeElement) e; + } + } + return null; + } + + public static List getDirectSuperTypes(TypeElement element) { + List types = new ArrayList<>(); + if (element.getSuperclass() != null) { + TypeElement superElement = fromTypeMirror(element.getSuperclass()); + if (superElement != null) { + types.add(superElement); + types.addAll(getDirectSuperTypes(superElement)); + } + } + + return types; + } + + public static List getSuperTypes(TypeElement element) { + List types = new ArrayList<>(); + List superTypes = null; + List superInterfaces = null; + if (element.getSuperclass() != null) { + TypeElement superElement = fromTypeMirror(element.getSuperclass()); + if (superElement != null) { + types.add(superElement); + superTypes = getSuperTypes(superElement); + } + } + for (TypeMirror interfaceMirror : element.getInterfaces()) { + TypeElement interfaceElement = fromTypeMirror(interfaceMirror); + if (interfaceElement != null) { + types.add(interfaceElement); + superInterfaces = getSuperTypes(interfaceElement); + } + } + + if (superTypes != null) { + types.addAll(superTypes); + } + + if (superInterfaces != null) { + types.addAll(superInterfaces); + } + + return types; + } + + public static String getPackageName(TypeElement element) { + return findPackageElement(element).getQualifiedName().toString(); + } + + public static String getPackageName(TypeMirror mirror) { + switch (mirror.getKind()) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case SHORT: + case INT: + case LONG: + case VOID: + case TYPEVAR: + return null; + case DECLARED: + PackageElement pack = findPackageElement(fromTypeMirror(mirror)); + if (pack == null) { + throw new IllegalArgumentException("No package element found for declared type " + getSimpleName(mirror)); + } + return pack.getQualifiedName().toString(); + case ARRAY: + return getSimpleName(((ArrayType) mirror).getComponentType()); + default: + throw new RuntimeException("Unknown type specified " + mirror.getKind()); + } + } + + public static String createConstantName(String simpleName) { + // TODO use camel case to produce underscores. + return simpleName.toString().toUpperCase(); + } + + public static TypeElement fromTypeMirror(TypeMirror mirror) { + switch (mirror.getKind()) { + case DECLARED: + return (TypeElement) ((DeclaredType) mirror).asElement(); + case ARRAY: + return fromTypeMirror(((ArrayType) mirror).getComponentType()); + default: + return null; + } + } + + @SuppressWarnings("unchecked") + public static List getAnnotationValueList(Class expectedListType, AnnotationMirror mirror, String name) { + List values = getAnnotationValue(List.class, mirror, name); + List result = new ArrayList<>(); + + if (values != null) { + for (AnnotationValue value : values) { + T annotationValue = resolveAnnotationValue(expectedListType, value); + if (annotationValue != null) { + result.add(annotationValue); + } + } + } + return result; + } + + public static T getAnnotationValue(Class expectedType, AnnotationMirror mirror, String name) { + return resolveAnnotationValue(expectedType, getAnnotationValue(mirror, name)); + } + + @SuppressWarnings({"unchecked"}) + private static T resolveAnnotationValue(Class expectedType, AnnotationValue value) { + if (value == null) { + return null; + } + + Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null); + if (unboxedValue != null) { + if (expectedType == TypeMirror.class && unboxedValue instanceof String) { + return null; + } + if (!expectedType.isAssignableFrom(unboxedValue.getClass())) { + throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName()); + } + } + return (T) unboxedValue; + } + + public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) { + ExecutableElement valueMethod = null; + for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) { + if (method.getSimpleName().toString().equals(name)) { + valueMethod = method; + break; + } + } + + if (valueMethod == null) { + return null; + } + + AnnotationValue value = mirror.getElementValues().get(valueMethod); + if (value == null) { + value = valueMethod.getDefaultValue(); + } + + return value; + } + + private static class AnnotationValueVisitorImpl extends AbstractAnnotationValueVisitor7 { + + @Override + public Object visitBoolean(boolean b, Void p) { + return Boolean.valueOf(b); + } + + @Override + public Object visitByte(byte b, Void p) { + return Byte.valueOf(b); + } + + @Override + public Object visitChar(char c, Void p) { + return c; + } + + @Override + public Object visitDouble(double d, Void p) { + return d; + } + + @Override + public Object visitFloat(float f, Void p) { + return f; + } + + @Override + public Object visitInt(int i, Void p) { + return i; + } + + @Override + public Object visitLong(long i, Void p) { + return i; + } + + @Override + public Object visitShort(short s, Void p) { + return s; + } + + @Override + public Object visitString(String s, Void p) { + return s; + } + + @Override + public Object visitType(TypeMirror t, Void p) { + return t; + } + + @Override + public Object visitEnumConstant(VariableElement c, Void p) { + return c; + } + + @Override + public Object visitAnnotation(AnnotationMirror a, Void p) { + return a; + } + + @Override + public Object visitArray(List vals, Void p) { + return vals; + } + + } + + public static boolean getAnnotationValueBoolean(AnnotationMirror mirror, String name) { + return (Boolean) getAnnotationValue(mirror, name).getValue(); + } + + public static String printException(Throwable e) { + StringWriter string = new StringWriter(); + PrintWriter writer = new PrintWriter(string); + e.printStackTrace(writer); + writer.flush(); + return e.getMessage() + "\r\n" + string.toString(); + } + + public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, Element element, Class annotationClass) { + return findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), annotationClass); + } + + public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List mirrors, Class annotationClass) { + TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName()); + for (AnnotationMirror mirror : mirrors) { + DeclaredType annotationType = mirror.getAnnotationType(); + TypeElement actualAnnotationType = (TypeElement) annotationType.asElement(); + if (actualAnnotationType.equals(expectedAnnotationType)) { + return mirror; + } + } + return null; + } + + private static PackageElement findPackageElement(Element type) { + List hierarchy = getElementHierarchy(type); + for (Element element : hierarchy) { + if (element.getKind() == ElementKind.PACKAGE) { + return (PackageElement) element; + } + } + return null; + } + + public static String firstLetterUpperCase(String name) { + if (name == null || name.isEmpty()) { + return name; + } + return Character.toUpperCase(name.charAt(0)) + name.substring(1, name.length()); + } + + public static String firstLetterLowerCase(String name) { + if (name == null || name.isEmpty()) { + return name; + } + return Character.toLowerCase(name.charAt(0)) + name.substring(1, name.length()); + } + + private static ExecutableElement getDeclaredMethod(TypeElement element, String name, TypeMirror[] params) { + List methods = ElementFilter.methodsIn(element.getEnclosedElements()); + method: for (ExecutableElement method : methods) { + if (!method.getSimpleName().toString().equals(name)) { + continue; + } + if (method.getParameters().size() != params.length) { + continue; + } + for (int i = 0; i < params.length; i++) { + TypeMirror param1 = params[i]; + TypeMirror param2 = method.getParameters().get(i).asType(); + if (param1.getKind() != TypeKind.TYPEVAR && param2.getKind() != TypeKind.TYPEVAR) { + if (!getQualifiedName(param1).equals(getQualifiedName(param2))) { + continue method; + } + } + } + return method; + } + return null; + } + + private static boolean isDeclaredMethod(TypeElement element, String name, TypeMirror[] params) { + return getDeclaredMethod(element, name, params) != null; + } + + public static boolean isDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) { + List superElements = getSuperTypes(element); + + for (TypeElement typeElement : superElements) { + if (isDeclaredMethod(typeElement, name, params)) { + return true; + } + } + return false; + } + + private static ExecutableElement getDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) { + List superElements = getSuperTypes(element); + + for (TypeElement typeElement : superElements) { + ExecutableElement declared = getDeclaredMethod(typeElement, name, params); + if (declared != null) { + return declared; + } + } + return null; + } + + public static ExecutableElement getDeclaredMethodRecursive(TypeElement element, String name, TypeMirror[] params) { + ExecutableElement declared = getDeclaredMethod(element, name, params); + if (declared != null) { + return declared; + } + return getDeclaredMethodInSuperType(element, name, params); + } + + public static boolean typeEquals(TypeMirror type1, TypeMirror type2) { + if (type1 == null && type2 == null) { + return true; + } else if (type1 == null || type2 == null) { + return false; + } + String qualified1 = getQualifiedName(type1); + String qualified2 = getQualifiedName(type2); + + if (type1.getKind() == TypeKind.ARRAY || type2.getKind() == TypeKind.ARRAY) { + if (type1.getKind() == TypeKind.ARRAY && type2.getKind() == TypeKind.ARRAY) { + return typeEquals(((ArrayType) type1).getComponentType(), ((ArrayType) type2).getComponentType()); + } else { + return false; + } + } + return qualified1.equals(qualified2); + } + + public static int compareByTypeHierarchy(TypeMirror t1, TypeMirror t2) { + if (typeEquals(t1, t2)) { + return 0; + } + Set t1SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t1))); + if (t1SuperSet.contains(getQualifiedName(t2))) { + return -1; + } + + Set t2SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t2))); + if (t2SuperSet.contains(getQualifiedName(t1))) { + return 1; + } + return 0; + } + + public static boolean canThrowType(List thrownTypes, TypeMirror exceptionType) { + if (Utils.containsType(thrownTypes, exceptionType)) { + return true; + } + + if (isRuntimeException(exceptionType)) { + return true; + } + + // search for any super types + TypeElement exceptionTypeElement = fromTypeMirror(exceptionType); + List superTypes = getSuperTypes(exceptionTypeElement); + for (TypeElement typeElement : superTypes) { + if (Utils.containsType(thrownTypes, typeElement.asType())) { + return true; + } + } + + return false; + } + + public static Modifier getVisibility(Set modifier) { + for (Modifier mod : modifier) { + if (mod == Modifier.PUBLIC || mod == Modifier.PRIVATE || mod == Modifier.PROTECTED) { + return mod; + } + } + return null; + } + + private static boolean isRuntimeException(TypeMirror type) { + Set typeSuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(type))); + String typeName = getQualifiedName(type); + if (!typeSuperSet.contains(Throwable.class.getCanonicalName()) && !typeName.equals(Throwable.class.getCanonicalName())) { + throw new IllegalArgumentException("Given type does not extend Throwable."); + } + return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || typeName.equals(RuntimeException.class.getCanonicalName()); + } + + private static boolean containsType(Collection collection, TypeMirror type) { + for (TypeMirror otherTypeMirror : collection) { + if (typeEquals(otherTypeMirror, type)) { + return true; + } + } + return false; + } + + public static boolean isTopLevelClass(TypeMirror importType) { + TypeElement type = fromTypeMirror(importType); + if (type != null && type.getEnclosingElement() != null) { + return !type.getEnclosingElement().getKind().isClass(); + } + return true; + } + + public static boolean isObject(TypeMirror actualType) { + return getQualifiedName(actualType).equals("java.lang.Object"); + } + + public static boolean isFieldAccessible(Element element, VariableElement variable) { + TypeElement type = Utils.findNearestEnclosingType(element); + TypeElement varType = Utils.findNearestEnclosingType(variable); + + while (type != null) { + if (typeEquals(type.asType(), varType.asType())) { + return true; + } + if (type.getSuperclass() != null) { + type = Utils.fromTypeMirror(type.getSuperclass()); + } else { + type = null; + } + } + return false; + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/ExtensionContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/ExtensionContext.java Mon Jul 01 20:58:32 2013 +0200 @@ -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.api; + +import javax.annotation.processing.*; + +import com.oracle.truffle.dsl.processor.api.element.*; + +public interface ExtensionContext { + + ProcessingEnvironment getProcessingEnvironment(); + + RoundEnvironment getRoundEnvironment(); + + WritableElementFactory getElementFactory(); + + void addGeneratedElement(WritableElement element); + + void removeGeneratedElement(WritableElement element); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/ExtensionProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/ExtensionProcessor.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,31 @@ +/* + * 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.api; + +import javax.lang.model.element.*; + +public interface ExtensionProcessor { + + void process(ExtensionContext context, AnnotationMirror mirror, Element element); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableAnnotationMirror.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableAnnotationMirror.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.api.element; + +import javax.lang.model.element.*; + +public interface WritableAnnotationMirror extends AnnotationMirror { + + void setElementValue(ExecutableElement valueName, AnnotationValue value); + + AnnotationValue getElementValue(ExecutableElement valueName); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableElement.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.api.element; + +import javax.lang.model.element.*; + +public interface WritableElement extends Element { + + void addAnnotationMirror(AnnotationMirror annotationMirror); + + void removeAnnotationMirror(AnnotationMirror annotationMirror); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableElementFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableElementFactory.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,48 @@ +/* + * 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.api.element; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public interface WritableElementFactory { + + WritableExecutableElement cloneExecutableElement(ExecutableElement method); + + WritableVariableElement cloneVariableElement(VariableElement parameter); + + WritableAnnotationMirror cloneAnnotationMirror(AnnotationMirror mirror); + + WritableVariableElement createParameter(TypeMirror type, String simpleName); + + WritableExecutableElement createExecutableElement(TypeMirror returnType, String methodName); + + WritableAnnotationMirror createAnnotationMirror(DeclaredType annotationClass); + + Name createName(String name); + + AnnotationValue createAnnotationValue(Object value); + + TypeMirror createTypeMirror(Class javaClass); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableExecutableElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableExecutableElement.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,49 @@ +/* + * 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.api.element; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public interface WritableExecutableElement extends ExecutableElement, WritableElement { + + void setReturnType(TypeMirror type); + + void setDefaultValue(AnnotationValue defaultValue); + + void addParameter(VariableElement parameter); + + void removeParameter(VariableElement parameter); + + void addThrownType(TypeMirror thrownType); + + void removeThrownType(TypeMirror thrownType); + + void setSimpleName(Name name); + + void setVarArgs(boolean varargs); + + void setBody(String body); + + String getBody(); +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableVariableElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/api/element/WritableVariableElement.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,34 @@ +/* + * 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.api.element; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public interface WritableVariableElement extends VariableElement, WritableElement { + + void setSimpleName(Name name); + + void setType(TypeMirror type); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationMirror.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationMirror.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,74 @@ +/* + * 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.ast; + +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.api.element.*; + +public class CodeAnnotationMirror implements WritableAnnotationMirror { + + private final DeclaredType annotationType; + private final Map values = new LinkedHashMap<>(); + + public CodeAnnotationMirror(DeclaredType annotationType) { + this.annotationType = annotationType; + } + + @Override + public DeclaredType getAnnotationType() { + return annotationType; + } + + @Override + public Map getElementValues() { + return values; + } + + @Override + public AnnotationValue getElementValue(ExecutableElement method) { + return values.get(method); + } + + @Override + public void setElementValue(ExecutableElement method, AnnotationValue value) { + values.put(method, value); + } + + public ExecutableElement findExecutableElement(String name) { + return Utils.findExecutableElement(annotationType, name); + } + + public static CodeAnnotationMirror clone(AnnotationMirror mirror) { + CodeAnnotationMirror copy = new CodeAnnotationMirror(mirror.getAnnotationType()); + for (ExecutableElement key : mirror.getElementValues().keySet()) { + copy.setElementValue(key, mirror.getElementValues().get(key)); + } + return copy; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationValue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeAnnotationValue.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,84 @@ +/* + * 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.ast; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public class CodeAnnotationValue implements AnnotationValue { + + private final Object value; + + public CodeAnnotationValue(Object value) { + Objects.requireNonNull(value); + if ((value instanceof AnnotationMirror) || (value instanceof List) || (value instanceof Boolean) || (value instanceof Byte) || (value instanceof Character) || (value instanceof Double) || + (value instanceof VariableElement) || (value instanceof Float) || (value instanceof Integer) || (value instanceof Long) || (value instanceof Short) || + (value instanceof String) || (value instanceof TypeMirror)) { + this.value = value; + } else { + throw new IllegalArgumentException("Invalid annotation value type " + value.getClass().getName()); + } + } + + @Override + public Object getValue() { + return value; + } + + @SuppressWarnings("unchecked") + @Override + public R accept(AnnotationValueVisitor v, P p) { + if (value instanceof AnnotationMirror) { + return v.visitAnnotation((AnnotationMirror) value, p); + } else if (value instanceof List) { + return v.visitArray((List) value, p); + } else if (value instanceof Boolean) { + return v.visitBoolean((boolean) value, p); + } else if (value instanceof Byte) { + return v.visitByte((byte) value, p); + } else if (value instanceof Character) { + return v.visitChar((char) value, p); + } else if (value instanceof Double) { + return v.visitDouble((double) value, p); + } else if (value instanceof VariableElement) { + return v.visitEnumConstant((VariableElement) value, p); + } else if (value instanceof Float) { + return v.visitFloat((float) value, p); + } else if (value instanceof Integer) { + return v.visitInt((int) value, p); + } else if (value instanceof Long) { + return v.visitLong((long) value, p); + } else if (value instanceof Short) { + return v.visitShort((short) value, p); + } else if (value instanceof String) { + return v.visitString((String) value, p); + } else if (value instanceof TypeMirror) { + return v.visitType((TypeMirror) value, p); + } else { + return v.visitUnknown(this, p); + } + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeCompilationUnit.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeCompilationUnit.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,63 @@ +/* + * 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.ast; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public class CodeCompilationUnit extends CodeElement { + + public CodeCompilationUnit() { + super(Collections. emptySet()); + } + + @Override + public TypeMirror asType() { + throw new UnsupportedOperationException(); + } + + @Override + public ElementKind getKind() { + return ElementKind.OTHER; + } + + @Override + public Name getSimpleName() { + throw new UnsupportedOperationException(); + } + + @Override + public R accept(ElementVisitor v, P p) { + for (Element type : getEnclosedElements()) { + if (type.getKind().isClass()) { + type.accept(v, p); + } else { + throw new ClassCastException(type.getClass().getName()); + } + } + return null; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElement.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,360 @@ +/* + * 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.ast; + +import java.io.*; +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.api.element.*; +import com.oracle.truffle.dsl.processor.codewriter.*; + +public abstract class CodeElement implements WritableElement, GeneratedElement { + + private final Set modifiers; + private List annotations; + private List enclosedElements; + + private Element enclosingElement; + + private Element generatorElement; + private AnnotationMirror generatorAnnotationMirror; + + public CodeElement() { + this.modifiers = new LinkedHashSet<>(); + } + + @Override + public void setGeneratorAnnotationMirror(AnnotationMirror mirror) { + this.generatorAnnotationMirror = mirror; + } + + @Override + public void setGeneratorElement(Element element) { + this.generatorElement = element; + } + + @Override + public AnnotationMirror getGeneratorAnnotationMirror() { + return generatorAnnotationMirror; + } + + @Override + public Element getGeneratorElement() { + return generatorElement; + } + + public CodeElement(Set modifiers) { + this.modifiers = new LinkedHashSet<>(modifiers); + } + + public E add(E element) { + if (element == null) { + throw new NullPointerException(); + } + getEnclosedElements().add(element); + return element; + } + + public void remove(E element) { + getEnclosedElements().remove(element); + } + + @Override + public Set getModifiers() { + return modifiers; + } + + @Override + public List getEnclosedElements() { + if (enclosedElements == null) { + enclosedElements = parentableList(this, new ArrayList()); + } + return enclosedElements; + } + + @Override + public List getAnnotationMirrors() { + if (annotations == null) { + annotations = parentableList(this, new ArrayList()); + } + return annotations; + } + + /** + * Support JDK8 langtools. + * + * @param annotationType + */ + public A[] getAnnotationsByType(Class annotationType) { + throw new UnsupportedOperationException(); + } + + /** + * Support for some JDK8 builds. (remove after jdk8 is released) + * + * @param annotationType + */ + public A[] getAnnotations(Class annotationType) { + throw new UnsupportedOperationException(); + } + + /** + * Support for some JDK8 builds. (remove after jdk8 is released) + * + * @param annotationType + */ + public A getAnnotation(Class annotationType) { + throw new UnsupportedOperationException(); + } + + @Override + public void addAnnotationMirror(AnnotationMirror annotationMirror) { + getAnnotationMirrors().add(annotationMirror); + } + + public void removeAnnotationMirror(AnnotationMirror annotationMirror) { + getAnnotationMirrors().remove(annotationMirror); + } + + void setEnclosingElement(Element parent) { + this.enclosingElement = parent; + } + + public Element getEnclosingElement() { + return enclosingElement; + } + + public CodeTypeElement getEnclosingClass() { + Element p = enclosingElement; + while (p != null && p.getKind() != ElementKind.CLASS && p.getKind() != ElementKind.ENUM) { + p = p.getEnclosingElement(); + } + return (CodeTypeElement) p; + } + + List parentableList(Element parent, List list) { + return new ParentableList<>(parent, list); + } + + @Override + public String toString() { + StringBuilderCodeWriter codeWriter = new StringBuilderCodeWriter(); + accept(codeWriter, null); + return codeWriter.getString(); + } + + private static class StringBuilderCodeWriter extends AbstractCodeWriter { + + public StringBuilderCodeWriter() { + this.writer = new CharArrayWriter(); + } + + @Override + protected Writer createWriter(CodeTypeElement clazz) throws IOException { + return writer; + } + + public String getString() { + return new String(((CharArrayWriter) writer).toCharArray()).trim(); + } + + } + + private static class ParentableList implements List { + + private final Element parent; + private final List delegate; + + public ParentableList(Element parent, List delegate) { + this.parent = parent; + this.delegate = delegate; + } + + private void addImpl(T element) { + if (element != null) { + if (element instanceof CodeElement) { + ((CodeElement) element).setEnclosingElement(parent); + } + } + } + + private static void removeImpl(Object element) { + if (element instanceof CodeElement) { + ((CodeElement) element).setEnclosingElement(null); + } + } + + @Override + public int size() { + return delegate.size(); + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return delegate.contains(o); + } + + @Override + public Iterator iterator() { + return delegate.iterator(); + } + + @Override + public Object[] toArray() { + return delegate.toArray(); + } + + @Override + public E[] toArray(E[] a) { + return delegate.toArray(a); + } + + @Override + public boolean add(T e) { + addImpl(e); + return delegate.add(e); + } + + @Override + public boolean remove(Object o) { + boolean removed = delegate.remove(o); + if (removed) { + removeImpl(o); + } + return removed; + } + + @Override + public boolean containsAll(Collection c) { + return delegate.containsAll(c); + } + + @Override + public boolean addAll(Collection c) { + if (c != null) { + for (T t : c) { + addImpl(t); + } + } + return delegate.addAll(c); + } + + @Override + public boolean addAll(int index, Collection c) { + if (c != null) { + for (T t : c) { + addImpl(t); + } + } + return delegate.addAll(index, c); + } + + @Override + public boolean removeAll(Collection c) { + if (c != null) { + for (Object t : c) { + removeImpl(t); + } + } + return delegate.removeAll(c); + } + + @Override + public String toString() { + return delegate.toString(); + } + + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException("Not supported by parentable list"); + } + + @Override + public void clear() { + for (Object e : this) { + removeImpl(e); + } + delegate.clear(); + } + + @Override + public T get(int index) { + return delegate.get(index); + } + + @Override + public T set(int index, T element) { + removeImpl(delegate.get(index)); + addImpl(element); + return delegate.set(index, element); + } + + @Override + public void add(int index, T element) { + addImpl(element); + delegate.add(index, element); + } + + @Override + public T remove(int index) { + T element = delegate.remove(index); + removeImpl(element); + return element; + } + + @Override + public int indexOf(Object o) { + return delegate.indexOf(o); + } + + @Override + public int lastIndexOf(Object o) { + return delegate.lastIndexOf(o); + } + + @Override + public ListIterator listIterator() { + return delegate.listIterator(); + } + + @Override + public ListIterator listIterator(int index) { + return delegate.listIterator(index); + } + + @Override + public List subList(int fromIndex, int toIndex) { + return new ParentableList<>(parent, delegate.subList(fromIndex, toIndex)); + } + + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElementScanner.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeElementScanner.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,76 @@ +/* + * 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.ast; + +import javax.lang.model.element.*; +import javax.lang.model.util.*; + +public abstract class CodeElementScanner extends ElementScanner7 { + + @Override + public final R visitExecutable(ExecutableElement e, P p) { + return visitExecutable(cast(e, CodeExecutableElement.class), p); + } + + public R visitExecutable(CodeExecutableElement e, P p) { + R ret = super.visitExecutable(e, p); + if (e.getBodyTree() != null) { + visitTree(e.getBodyTree(), p); + } + return ret; + } + + @Override + public R visitPackage(PackageElement e, P p) { + return super.visitPackage(e, p); + } + + @Override + public final R visitType(TypeElement e, P p) { + return visitType(cast(e, CodeTypeElement.class), p); + } + + public R visitType(CodeTypeElement e, P p) { + return super.visitType(e, p); + } + + @Override + public R visitTypeParameter(TypeParameterElement e, P p) { + return super.visitTypeParameter(e, p); + } + + private static E cast(Element element, Class clazz) { + return clazz.cast(element); + } + + public void visitTree(CodeTree e, P p) { + for (CodeTree tree : e.getEnclosedElements()) { + tree.acceptCodeElementScanner(this, p); + } + } + + @SuppressWarnings("unused") + public void visitImport(CodeImport e, P p) { + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeExecutableElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeExecutableElement.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,231 @@ +/* + * 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.ast; + +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.api.element.*; + +public class CodeExecutableElement extends CodeElement implements WritableExecutableElement { + + private final List throwables = new ArrayList<>(); + private final List parameters = parentableList(this, new ArrayList()); + + private TypeMirror returnType; + private Name name; + + private CodeTree bodyTree; + private String body; + private AnnotationValue defaultValue; + private boolean varArgs; + + public CodeExecutableElement(TypeMirror returnType, String name) { + super(Utils.modifiers()); + this.returnType = returnType; + this.name = CodeNames.of(name); + } + + public CodeExecutableElement(Set modifiers, TypeMirror returnType, String name, CodeVariableElement... parameters) { + super(modifiers); + this.returnType = returnType; + this.name = CodeNames.of(name); + for (CodeVariableElement codeParameter : parameters) { + addParameter(codeParameter); + } + } + + /* Support JDK8 langtools. */ + public boolean isDefault() { + return false; + } + + @Override + public List getThrownTypes() { + return throwables; + } + + @Override + public TypeMirror asType() { + return returnType; + } + + @Override + public ElementKind getKind() { + if (getReturnType() == null) { + return ElementKind.CONSTRUCTOR; + } else { + return ElementKind.METHOD; + } + } + + @Override + public List getTypeParameters() { + return Collections.emptyList(); + } + + @Override + public void setVarArgs(boolean varargs) { + this.varArgs = varargs; + } + + @Override + public boolean isVarArgs() { + return varArgs; + } + + @Override + public void setDefaultValue(AnnotationValue defaultValue) { + this.defaultValue = defaultValue; + } + + @Override + public AnnotationValue getDefaultValue() { + return defaultValue; + } + + @Override + public Name getSimpleName() { + return name; + } + + public CodeTreeBuilder createBuilder() { + CodeTreeBuilder builder = new CodeTreeBuilder(null); + this.bodyTree = builder.getTree(); + this.bodyTree.setEnclosingElement(this); + this.body = null; + return builder; + } + + public void setBodyTree(CodeTree body) { + this.bodyTree = body; + } + + public CodeTree getBodyTree() { + return bodyTree; + } + + public TypeMirror getReturnType() { + return returnType; + } + + @Override + public List getParameters() { + return parameters; + } + + public TypeMirror[] getParameterTypes() { + TypeMirror[] types = new TypeMirror[getParameters().size()]; + for (int i = 0; i < types.length; i++) { + types[i] = parameters.get(i).asType(); + } + return types; + } + + @Override + public void setReturnType(TypeMirror type) { + returnType = type; + } + + @Override + public void addParameter(VariableElement parameter) { + parameters.add(parameter); + } + + @Override + public void removeParameter(VariableElement parameter) { + parameters.remove(parameter); + } + + public void removeParameter(String varName) { + VariableElement remove = null; + for (VariableElement var : getParameters()) { + if (var.getSimpleName().toString().equals(varName)) { + remove = var; + break; + } + } + if (remove != null) { + parameters.remove(remove); + } + } + + @Override + public void addThrownType(TypeMirror thrownType) { + throwables.add(thrownType); + } + + @Override + public void removeThrownType(TypeMirror thrownType) { + throwables.remove(thrownType); + } + + @Override + public void setSimpleName(Name name) { + this.name = name; + } + + @Override + public void setBody(String body) { + this.body = body; + } + + @Override + public String getBody() { + return body; + } + + @Override + public R accept(ElementVisitor v, P p) { + return v.visitExecutable(this, p); + } + + public static CodeExecutableElement clone(@SuppressWarnings("unused") ProcessingEnvironment env, ExecutableElement method) { + CodeExecutableElement copy = new CodeExecutableElement(method.getReturnType(), method.getSimpleName().toString()); + for (TypeMirror thrownType : method.getThrownTypes()) { + copy.addThrownType(thrownType); + } + copy.setDefaultValue(method.getDefaultValue()); + + for (AnnotationMirror mirror : method.getAnnotationMirrors()) { + copy.addAnnotationMirror(mirror); + } + for (VariableElement var : method.getParameters()) { + copy.addParameter(CodeVariableElement.clone(var)); + } + for (Element element : method.getEnclosedElements()) { + copy.add(element); + } + copy.getModifiers().addAll(method.getModifiers()); + copy.setVarArgs(method.isVarArgs()); + return copy; + } + + public TypeMirror getReceiverType() { + throw new UnsupportedOperationException(); + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeImport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeImport.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,100 @@ +/* + * 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.ast; + +import javax.lang.model.type.*; + +public class CodeImport implements Comparable { + + private final TypeMirror importType; + private final String importString; + private final boolean staticImport; + + public CodeImport(TypeMirror importedType, String importString, boolean staticImport) { + this.importType = importedType; + this.importString = importString; + this.staticImport = staticImport; + } + + public TypeMirror getImportType() { + return importType; + } + + public boolean isStaticImport() { + return staticImport; + } + + public String getImportString() { + return importString; + } + + @Override + public int compareTo(CodeImport o) { + if (staticImport && !o.staticImport) { + return 1; + } else if (!staticImport && o.staticImport) { + return -1; + } else { + return importString.compareTo(o.getImportString()); + } + } + + public

void accept(CodeElementScanner s, P p) { + s.visitImport(this, p); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((importString == null) ? 0 : importString.hashCode()); + result = prime * result + (staticImport ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + CodeImport other = (CodeImport) obj; + if (importString == null) { + if (other.importString != null) { + return false; + } + } else if (!importString.equals(other.importString)) { + return false; + } + if (staticImport != other.staticImport) { + return false; + } + return true; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeNames.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeNames.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,90 @@ +/* + * 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.ast; + +import java.util.*; + +import javax.lang.model.element.*; + +public abstract class CodeNames { + + private static Map names = new HashMap<>(); + + public static Name of(String value) { + Name name = names.get(value); + if (name == null) { + name = new NameImpl(value); + names.put(value, name); + } + return name; + } + + private static class NameImpl implements Name { + + private final String name; + + public NameImpl(String name) { + this.name = name; + } + + @Override + public int length() { + return name.length(); + } + + @Override + public char charAt(int index) { + return name.charAt(index); + } + + @Override + public CharSequence subSequence(int start, int end) { + return name.subSequence(start, end); + } + + @Override + public boolean contentEquals(CharSequence cs) { + return name.contentEquals(cs); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Name) { + return ((Name) obj).contentEquals(name); + } + return super.equals(obj); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public String toString() { + return name; + } + + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTree.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTree.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,81 @@ +/* + * 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.ast; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public class CodeTree extends CodeElement { + + private final CodeTreeKind kind; + + private final TypeMirror type; + private final String string; + + public CodeTree(CodeTreeKind kind, TypeMirror type, String string) { + this.kind = kind; + this.type = type; + this.string = string; + } + + public TypeMirror getType() { + return type; + } + + public CodeTreeKind getCodeKind() { + return kind; + } + + public String getString() { + return string; + } + + public

void acceptCodeElementScanner(CodeElementScanner s, P p) { + s.visitTree(this, p); + } + + @Override + public TypeMirror asType() { + return type; + } + + @Override + public ElementKind getKind() { + return ElementKind.OTHER; + } + + @Override + public Name getSimpleName() { + return CodeNames.of(getString()); + } + + @Override + public R accept(ElementVisitor v, P p) { + if (v instanceof CodeElementScanner) { + acceptCodeElementScanner((CodeElementScanner) v, p); + return null; + } else { + throw new UnsupportedOperationException(); + } + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeBuilder.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,818 @@ +/* + * 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.ast; + +import static com.oracle.truffle.dsl.processor.ast.CodeTreeKind.*; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.*; + +public class CodeTreeBuilder { + + private final CodeTreeBuilder parent; + + private BuilderCodeTree currentElement; + private final BuilderCodeTree root; + + private int treeCount; + + public CodeTreeBuilder(CodeTreeBuilder parent) { + this.root = new BuilderCodeTree(GROUP, null, null); + this.currentElement = root; + this.parent = parent; + } + + @Override + public String toString() { + return root.toString(); + } + + public int getTreeCount() { + return treeCount; + } + + public boolean isEmpty() { + return treeCount == 0; + } + + public CodeTreeBuilder statement(String statement) { + return startStatement().string(statement).end(); + } + + public CodeTreeBuilder statement(CodeTree statement) { + return startStatement().tree(statement).end(); + } + + public static CodeTreeBuilder createBuilder() { + return new CodeTreeBuilder(null); + } + + public static CodeTree singleString(String s) { + return new CodeTreeBuilder(null).string(s).getTree(); + } + + public static CodeTree singleType(TypeMirror s) { + return new CodeTreeBuilder(null).type(s).getTree(); + } + + private CodeTreeBuilder push(CodeTreeKind kind) { + return push(new BuilderCodeTree(kind, null, null)); + } + + private CodeTreeBuilder push(String string) { + return push(new BuilderCodeTree(CodeTreeKind.STRING, null, string)); + } + + private CodeTreeBuilder push(TypeMirror type) { + return push(new BuilderCodeTree(CodeTreeKind.TYPE, type, null)); + } + + private CodeTreeBuilder push(CodeTreeKind kind, TypeMirror type, String string) { + return push(new BuilderCodeTree(kind, type, string)); + } + + private CodeTreeBuilder push(BuilderCodeTree tree) { + if (currentElement != null) { + currentElement.add(tree); + } + switch (tree.getCodeKind()) { + case COMMA_GROUP: + case GROUP: + case INDENT: + currentElement = tree; + break; + } + treeCount++; + return this; + } + + private void clearLast(CodeTreeKind kind) { + if (clearLastRec(kind, currentElement.getEnclosedElements())) { + treeCount--; + } + } + + public CodeTreeBuilder startStatement() { + startGroup(); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + string(";").newLine(); + } + + @Override + public void afterEnd() { + } + }); + return this; + } + + public CodeTreeBuilder startGroup() { + return push(CodeTreeKind.GROUP); + } + + public CodeTreeBuilder startCommaGroup() { + return push(CodeTreeKind.COMMA_GROUP); + } + + public CodeTreeBuilder startCall(String callSite) { + return startCall(null, callSite); + } + + public CodeTreeBuilder startCall(String receiver, String callSite) { + if (receiver == null) { + return startGroup().string(callSite).startParanthesesCommaGroup().endAfter(); + } else { + return startGroup().string(receiver).string(".").string(callSite).startParanthesesCommaGroup().endAfter(); + } + } + + public CodeTreeBuilder startStaticCall(TypeMirror type, String methodName) { + return startGroup().push(CodeTreeKind.STATIC_METHOD_REFERENCE, type, methodName).startParanthesesCommaGroup().endAfter(); + } + + public CodeTreeBuilder startStaticCall(ExecutableElement method) { + return startStaticCall(Utils.findNearestEnclosingType(method).asType(), method.getSimpleName().toString()); + } + + public CodeTreeBuilder staticReference(TypeMirror type, String fieldName) { + return push(CodeTreeKind.STATIC_FIELD_REFERENCE, type, fieldName); + } + + private CodeTreeBuilder endAndWhitespaceAfter() { + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + string(" "); + end(); + } + }); + return this; + } + + private CodeTreeBuilder endAfter() { + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + end(); + } + }); + return this; + } + + private CodeTreeBuilder startParanthesesCommaGroup() { + startGroup(); + string("(").startCommaGroup(); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + string(")"); + } + }); + endAfter(); + return this; + } + + private CodeTreeBuilder startCurlyBracesCommaGroup() { + startGroup(); + string("{").startCommaGroup(); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + string("}"); + } + }); + endAfter(); + return this; + } + + public CodeTreeBuilder startParantheses() { + startGroup(); + string("(").startGroup(); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + string(")"); + } + }); + endAfter(); + return this; + } + + public CodeTreeBuilder doubleQuote(String s) { + return startGroup().string("\"" + s + "\"").end(); + } + + public CodeTreeBuilder string(String chunk1) { + return push(chunk1); + } + + public CodeTreeBuilder string(String chunk1, String chunk2) { + return push(GROUP).string(chunk1).string(chunk2).end(); + } + + public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3) { + return push(GROUP).string(chunk1).string(chunk2).string(chunk3).end(); + } + + public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4) { + return push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4).end(); + } + + public CodeTreeBuilder tree(CodeTree treeToAdd) { + if (treeToAdd instanceof BuilderCodeTree) { + return push((BuilderCodeTree) treeToAdd).end(); + } else { + BuilderCodeTree tree = new BuilderCodeTree(GROUP, null, null); + tree.add(treeToAdd); + return push(tree).end(); + } + } + + public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4, String... chunks) { + push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4); + for (int i = 0; i < chunks.length; i++) { + string(chunks[i]); + } + return end(); + } + + public CodeTreeBuilder dot() { + return string("."); + } + + public CodeTreeBuilder newLine() { + return push(NEW_LINE); + } + + public CodeTreeBuilder startWhile() { + return startGroup().string("while ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); + } + + public CodeTreeBuilder startIf() { + return startGroup().string("if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); + } + + public boolean startIf(boolean elseIf) { + if (elseIf) { + startElseIf(); + } else { + startIf(); + } + return true; + } + + public CodeTreeBuilder startElseIf() { + clearLast(CodeTreeKind.NEW_LINE); + return startGroup().string(" else if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); + } + + public CodeTreeBuilder startElseBlock() { + clearLast(CodeTreeKind.NEW_LINE); + return startGroup().string(" else ").startBlock().endAfter(); + } + + private boolean clearLastRec(CodeTreeKind kind, List children) { + for (int i = children.size() - 1; i >= 0; i--) { + CodeTree child = children.get(i); + if (child.getCodeKind() == kind) { + children.remove(children.get(i)); + return true; + } else { + if (clearLastRec(kind, child.getEnclosedElements())) { + return true; + } + } + } + return false; + } + + public CodeTreeBuilder startCase() { + startGroup().string("case "); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + string(" :").newLine(); + } + + @Override + public void afterEnd() { + } + }); + return this; + } + + public CodeTreeBuilder caseDefault() { + return startGroup().string("default :").newLine().end(); + } + + public CodeTreeBuilder startSwitch() { + return startGroup().string("switch ").startParanthesesCommaGroup().endAndWhitespaceAfter(); + } + + public CodeTreeBuilder startReturn() { + ExecutableElement method = findMethod(); + if (method != null && Utils.isVoid(method.getReturnType())) { + startGroup(); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + string(";").newLine(); // complete statement to execute + } + + @Override + public void afterEnd() { + string("return").string(";").newLine(); // emit a return; + } + }); + return this; + } else { + return startStatement().string("return "); + } + } + + public CodeTreeBuilder startAssert() { + return startStatement().string("assert "); + } + + public CodeTreeBuilder startNewArray(ArrayType arrayType, CodeTree size) { + startGroup().string("new ").type(arrayType.getComponentType()).string("["); + if (size != null) { + tree(size); + } + string("]"); + if (size == null) { + string(" "); + startCurlyBracesCommaGroup().endAfter(); + } + return this; + } + + public CodeTreeBuilder startNew(TypeMirror uninializedNodeClass) { + return startGroup().string("new ").type(uninializedNodeClass).startParanthesesCommaGroup().endAfter(); + } + + public CodeTreeBuilder startNew(String typeName) { + return startGroup().string("new ").string(typeName).startParanthesesCommaGroup().endAfter(); + } + + public CodeTreeBuilder startIndention() { + return push(CodeTreeKind.INDENT); + } + + public CodeTreeBuilder end(int times) { + for (int i = 0; i < times; i++) { + end(); + } + return this; + } + + public CodeTreeBuilder end() { + BuilderCodeTree tree = currentElement; + EndCallback callback = tree.getAtEndListener(); + if (callback != null) { + callback.beforeEnd(); + toParent(); + callback.afterEnd(); + } else { + toParent(); + } + return this; + } + + private void toParent() { + Element parentElement = currentElement.getEnclosingElement(); + if (currentElement != root) { + this.currentElement = (BuilderCodeTree) parentElement; + } else { + this.currentElement = root; + } + } + + public CodeTreeBuilder startBlock() { + startGroup(); + string("{").newLine().startIndention(); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + string("}").newLine(); + } + }); + endAfter(); + return this; + } + + private void registerCallBack(EndCallback callback) { + currentElement.registerAtEnd(callback); + } + + public CodeTreeBuilder defaultDeclaration(TypeMirror type, String name) { + if (!Utils.isVoid(type)) { + startStatement(); + type(type); + string(" "); + string(name); + string(" = "); + defaultValue(type); + end(); // statement + } + return this; + } + + public CodeTreeBuilder declaration(TypeMirror type, String name, String init) { + return declaration(type, name, singleString(init)); + } + + public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTree init) { + if (Utils.isVoid(type)) { + startStatement(); + tree(init); + end(); + } else { + startStatement(); + type(type); + string(" "); + string(name); + if (init != null) { + string(" = "); + tree(init); + } + end(); // statement + } + return this; + } + + public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTreeBuilder init) { + if (init == this) { + throw new IllegalArgumentException("Recursive builder usage."); + } + return declaration(type, name, init.getTree()); + } + + public CodeTreeBuilder declaration(TypeMirror type, String name) { + return declaration(type, name, (CodeTree) null); + } + + public CodeTreeBuilder create() { + return new CodeTreeBuilder(this); + } + + public CodeTreeBuilder type(TypeMirror type) { + return push(type); + } + + public CodeTreeBuilder typeLiteral(TypeMirror type) { + return startGroup().type(type).string(".class").end(); + } + + private void assertRoot() { + if (currentElement != root) { + throw new IllegalStateException("CodeTreeBuilder was not ended properly."); + } + } + + public CodeTreeBuilder startCaseBlock() { + return startIndention(); + } + + public CodeTreeBuilder startThrow() { + return startStatement().string("throw "); + } + + public CodeTree getTree() { + assertRoot(); + return root; + } + + public CodeTree getRoot() { + return root; + } + + public CodeTreeBuilder cast(String baseClassName) { + string("(").string(baseClassName).string(") "); + return this; + } + + public CodeTreeBuilder cast(TypeMirror type, CodeTree content) { + if (Utils.isVoid(type)) { + tree(content); + return this; + } else if (type.getKind() == TypeKind.DECLARED && Utils.getQualifiedName(type).equals("java.lang.Object")) { + tree(content); + return this; + } else { + return startGroup().string("(").type(type).string(")").string(" ").tree(content).end(); + } + } + + public CodeTreeBuilder startSuperCall() { + return string("super").startParanthesesCommaGroup(); + } + + public CodeTreeBuilder returnFalse() { + return startReturn().string("false").end(); + } + + public CodeTreeBuilder returnStatement() { + return statement("return"); + } + + public ExecutableElement findMethod() { + Element element = currentElement; + while (element != null && (element.getKind() != ElementKind.METHOD && (element.getKind() != ElementKind.CONSTRUCTOR))) { + element = element.getEnclosingElement(); + } + ExecutableElement found = element != null ? (ExecutableElement) element : null; + if (found == null && parent != null) { + found = parent.findMethod(); + } + return found; + } + + public CodeTreeBuilder returnTrue() { + return startReturn().string("true").end(); + } + + public CodeTreeBuilder instanceOf(CodeTree var, CodeTree type) { + tree(var).string(" instanceof ").tree(type); + return this; + } + + public CodeTreeBuilder instanceOf(String var, String type) { + return instanceOf(singleString(var), singleString(type)); + } + + public CodeTreeBuilder instanceOf(String var, TypeMirror type) { + TypeElement element = Utils.fromTypeMirror(type); + if (element == null) { + throw new IllegalArgumentException("Cannot call instanceof for a non supported type: " + type.getKind()); + } + return instanceOf(singleString(var), singleType(type)); + } + + public CodeTreeBuilder defaultValue(TypeMirror mirror) { + switch (mirror.getKind()) { + case VOID: + return string(""); + case ARRAY: + case DECLARED: + case PACKAGE: + case NULL: + return string("null"); + case BOOLEAN: + return string("false"); + case BYTE: + return string("(byte) 0"); + case CHAR: + return string("(char) 0"); + case DOUBLE: + return string("0.0D"); + case LONG: + return string("0L"); + case INT: + return string("0"); + case FLOAT: + return string("0.0F"); + case SHORT: + return string("(short) 0"); + default: + throw new AssertionError(); + } + } + + public CodeTreeBuilder assertFalse() { + return startAssert().string("false").end(); + } + + public CodeTreeBuilder breakStatement() { + return statement("break"); + } + + public CodeTreeBuilder isNull() { + return string(" == null"); + } + + public CodeTreeBuilder isNotNull() { + return string(" != null"); + } + + public CodeTreeBuilder is(CodeTree tree) { + return string(" == ").tree(tree); + } + + public CodeTreeBuilder startTryBlock() { + return string("try ").startBlock(); + } + + public CodeTreeBuilder startCatchBlock(TypeMirror exceptionType, String localVarName) { + clearLast(CodeTreeKind.NEW_LINE); + string(" catch (").type(exceptionType).string(" ").string(localVarName).string(") "); + return startBlock(); + } + + public CodeTreeBuilder startFinallyBlock() { + clearLast(CodeTreeKind.NEW_LINE); + string(" finally "); + return startBlock(); + } + + public CodeTreeBuilder nullLiteral() { + return string("null"); + } + + private static class BuilderCodeTree extends CodeTree { + + private EndCallback atEndListener; + + public BuilderCodeTree(CodeTreeKind kind, TypeMirror type, String string) { + super(kind, type, string); + } + + public void registerAtEnd(EndCallback atEnd) { + if (this.atEndListener != null) { + this.atEndListener = new CompoundCallback(this.atEndListener, atEnd); + } else { + this.atEndListener = atEnd; + } + } + + public EndCallback getAtEndListener() { + return atEndListener; + } + + @Override + public String toString() { + final StringBuilder b = new StringBuilder(); + acceptCodeElementScanner(new Printer(b), null); + return b.toString(); + } + + private static class CompoundCallback implements EndCallback { + + private final EndCallback callback1; + private final EndCallback callback2; + + public CompoundCallback(EndCallback callback1, EndCallback callback2) { + this.callback1 = callback1; + this.callback2 = callback2; + } + + @Override + public void afterEnd() { + callback1.afterEnd(); + callback2.afterEnd(); + } + + @Override + public void beforeEnd() { + callback1.beforeEnd(); + callback1.beforeEnd(); + } + } + + } + + private interface EndCallback { + + void beforeEnd(); + + void afterEnd(); + } + + private static class Printer extends CodeElementScanner { + + private int indent; + private boolean newLine; + private final String ln = "\n"; + + private final StringBuilder b; + + Printer(StringBuilder b) { + this.b = b; + } + + @Override + public void visitTree(CodeTree e, Void p) { + switch (e.getCodeKind()) { + case COMMA_GROUP: + List children = e.getEnclosedElements(); + for (int i = 0; i < children.size(); i++) { + children.get(i).acceptCodeElementScanner(this, p); + if (i < e.getEnclosedElements().size() - 1) { + b.append(", "); + } + } + break; + case GROUP: + super.visitTree(e, p); + break; + case INDENT: + indent(); + super.visitTree(e, p); + dedent(); + break; + case NEW_LINE: + writeLn(); + break; + case STRING: + if (e.getString() != null) { + write(e.getString()); + } else { + write("null"); + } + break; + case TYPE: + write(Utils.getSimpleName(e.getType())); + break; + default: + assert false; + return; + } + } + + private void indent() { + indent++; + } + + private void dedent() { + indent--; + } + + private void writeLn() { + write(ln); + newLine = true; + } + + private void write(String m) { + if (newLine && m != ln) { + writeIndent(); + newLine = false; + } + b.append(m); + } + + private void writeIndent() { + for (int i = 0; i < indent; i++) { + b.append(" "); + } + } + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeKind.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeKind.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,27 @@ +/* + * 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.ast; + +public enum CodeTreeKind { + STATIC_FIELD_REFERENCE, STATIC_METHOD_REFERENCE, GROUP, COMMA_GROUP, INDENT, STRING, NEW_LINE, TYPE; +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeVariable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTreeVariable.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.ast; + +public class CodeTreeVariable extends CodeTree { + + private final String name; + + private CodeTree value; + + public CodeTreeVariable() { + super(CodeTreeKind.GROUP, null, null); + this.name = ""; + } + + public CodeTreeVariable(String name) { + super(CodeTreeKind.GROUP, null, null); + this.name = name; + } + + public String getName() { + return name; + } + + public void set(CodeTree tree) { + if (value == tree) { + return; + } + if (this.value != null) { + remove(this.value); + } + this.value = tree; + add(tree); + } + + public CodeTree get() { + return value; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeElement.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,212 @@ +/* + * 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.ast; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.dsl.processor.ast.CodeTypeMirror.*; + +public class CodeTypeElement extends CodeElement implements TypeElement { + + private final List imports = parentableList(this, new ArrayList()); + + private final PackageElement packageElement; + + private final Name simpleName; + private final Name packageName; + private Name qualifiedName; + + private final List implementsInterfaces = new ArrayList<>(); + private final ElementKind kind; + private TypeMirror superClass; + + private final DeclaredCodeTypeMirror mirror = new DeclaredCodeTypeMirror(this); + + public CodeTypeElement(Set modifiers, ElementKind kind, PackageElement packageElement, String simpleName) { + super(modifiers); + this.kind = kind; + this.packageElement = packageElement; + this.simpleName = CodeNames.of(simpleName); + if (this.packageElement != null) { + this.packageName = packageElement.getQualifiedName(); + } else { + this.packageName = CodeNames.of("default"); + } + this.qualifiedName = createQualifiedName(); + } + + @Override + public TypeMirror asType() { + return mirror; + } + + @Override + public ElementKind getKind() { + return kind; + } + + public boolean containsField(String name) { + for (VariableElement field : getFields()) { + if (field.getSimpleName().toString().equals(name)) { + return true; + } + } + return false; + } + + @Override + public NestingKind getNestingKind() { + return isTopLevelClass() ? NestingKind.TOP_LEVEL : NestingKind.LOCAL; + } + + @Override + public Element getEnclosingElement() { + if (isTopLevelClass()) { + return packageElement; + } else { + return super.getEnclosingElement(); + } + } + + @Override + public TypeMirror getSuperclass() { + return superClass; + } + + @Override + public List getInterfaces() { + return implementsInterfaces; + } + + @Override + public List getTypeParameters() { + return Collections.emptyList(); + } + + public boolean isTopLevelClass() { + return super.getEnclosingElement() instanceof CodeCompilationUnit; + } + + public CodeVariableElement getField(String name) { + for (VariableElement field : ElementFilter.fieldsIn(getEnclosedElements())) { + if (field.getSimpleName().toString().equals(name)) { + return (CodeVariableElement) field; + } + } + return null; + } + + private Name createQualifiedName() { + TypeElement enclosingType = getEnclosingClass(); + if (enclosingType == null) { + return CodeNames.of(packageName + "." + simpleName); + } else { + return CodeNames.of(enclosingType.getQualifiedName() + "." + simpleName); + } + } + + @Override + void setEnclosingElement(Element element) { + super.setEnclosingElement(element); + + // update qualified name on container change + this.qualifiedName = createQualifiedName(); + } + + public Name getPackageName() { + return packageName; + } + + @Override + public Name getQualifiedName() { + return qualifiedName; + } + + @Override + public Name getSimpleName() { + return simpleName; + } + + public void setSuperClass(TypeMirror superType) { + this.superClass = superType; + } + + public List getImports() { + return imports; + } + + public List getImplements() { + return implementsInterfaces; + } + + @Override + public int hashCode() { + return getQualifiedName().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof TypeElement) { + return getQualifiedName().equals(((TypeElement) obj).getQualifiedName()); + } + return false; + } + + public List getFields() { + return ElementFilter.fieldsIn(getEnclosedElements()); + } + + public ExecutableElement getMethod(String name) { + for (Element element : getEnclosedElements()) { + if (element.getKind() == ElementKind.METHOD && element.getSimpleName().toString().equals(name)) { + return (ExecutableElement) element; + } + } + return null; + } + + public List getMethods() { + return ElementFilter.methodsIn(getEnclosedElements()); + } + + public List getInnerClasses() { + return ElementFilter.typesIn(getEnclosedElements()); + } + + @Override + public String toString() { + return getQualifiedName().toString(); + } + + @Override + public R accept(ElementVisitor v, P p) { + return v.visitType(this, p); + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeMirror.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeTypeMirror.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,119 @@ +/* + * 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.ast; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public class CodeTypeMirror implements TypeMirror { + + private final TypeKind kind; + + public CodeTypeMirror(TypeKind kind) { + this.kind = kind; + } + + @Override + public TypeKind getKind() { + return kind; + } + + @Override + public R accept(TypeVisitor v, P p) { + throw new UnsupportedOperationException(); + } + + public static class ArrayCodeTypeMirror extends CodeTypeMirror implements ArrayType { + + private final TypeMirror component; + + public ArrayCodeTypeMirror(TypeMirror component) { + super(TypeKind.ARRAY); + this.component = component; + } + + @Override + public TypeMirror getComponentType() { + return component; + } + + } + + public static class DeclaredCodeTypeMirror extends CodeTypeMirror implements DeclaredType { + + private final TypeElement clazz; + private final List typeArguments; + + public DeclaredCodeTypeMirror(TypeElement clazz) { + this(clazz, Collections. emptyList()); + } + + public DeclaredCodeTypeMirror(TypeElement clazz, List typeArguments) { + super(TypeKind.DECLARED); + this.clazz = clazz; + this.typeArguments = typeArguments; + } + + @Override + public Element asElement() { + return clazz; + } + + @Override + public TypeMirror getEnclosingType() { + return clazz.getEnclosingElement().asType(); + } + + @Override + public List getTypeArguments() { + return typeArguments; + } + + @Override + public String toString() { + return clazz.getQualifiedName().toString(); + } + + } + + public List getAnnotationMirrors() { + throw new UnsupportedOperationException(); + } + + /** + * @param annotationType + */ + public A getAnnotation(Class annotationType) { + throw new UnsupportedOperationException(); + } + + /** + * @param annotationType + */ + public A[] getAnnotationsByType(Class annotationType) { + throw new UnsupportedOperationException(); + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeVariableElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/CodeVariableElement.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,143 @@ +/* + * 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.ast; + +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.api.element.*; + +public final class CodeVariableElement extends CodeElement implements WritableVariableElement { + + private Name name; + private TypeMirror type; + private Object constantValue; + + private CodeTree init; + + public CodeVariableElement(TypeMirror type, String name) { + super(Utils.modifiers()); + this.type = type; + this.name = CodeNames.of(name); + } + + public CodeVariableElement(Set modifiers, TypeMirror type, String name) { + super(modifiers); + this.type = type; + this.name = CodeNames.of(name); + } + + public CodeVariableElement(Set modifiers, TypeMirror type, String name, String init) { + this(modifiers, type, name); + if (init != null) { + this.init = new CodeTree(CodeTreeKind.STRING, null, init); + } + } + + public CodeTreeBuilder createInitBuilder() { + CodeTreeBuilder builder = new CodeTreeBuilder(null); + init = builder.getTree(); + init.setEnclosingElement(this); + return builder; + } + + public void setInit(CodeTree init) { + this.init = init; + } + + public CodeTree getInit() { + return init; + } + + public Name getSimpleName() { + return name; + } + + public TypeMirror getType() { + return type; + } + + @Override + public TypeMirror asType() { + return type; + } + + @Override + public ElementKind getKind() { + if (getEnclosingElement() instanceof ExecutableElement) { + return ElementKind.PARAMETER; + } else if (getEnclosingElement() instanceof TypeElement) { + return ElementKind.FIELD; + } else { + return ElementKind.PARAMETER; + } + } + + public void setConstantValue(Object constantValue) { + this.constantValue = constantValue; + } + + @Override + public Object getConstantValue() { + return constantValue; + } + + public String getName() { + return getSimpleName().toString(); + } + + @Override + public void setSimpleName(Name name) { + this.name = name; + } + + public void setName(String name) { + this.name = CodeNames.of(name); + } + + @Override + public void setType(TypeMirror type) { + this.type = type; + } + + @Override + public R accept(ElementVisitor v, P p) { + return v.visitVariable(this, p); + } + + public static CodeVariableElement clone(VariableElement var) { + CodeVariableElement copy = new CodeVariableElement(var.getModifiers(), var.asType(), var.getSimpleName().toString()); + copy.setConstantValue(var.getConstantValue()); + for (AnnotationMirror mirror : var.getAnnotationMirrors()) { + copy.addAnnotationMirror(mirror); + } + for (Element element : var.getEnclosedElements()) { + copy.add(element); + } + return copy; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/GeneratedElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ast/GeneratedElement.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,37 @@ +/* + * 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.ast; + +import javax.lang.model.element.*; + +public interface GeneratedElement { + + AnnotationMirror getGeneratorAnnotationMirror(); + + void setGeneratorAnnotationMirror(AnnotationMirror mirror); + + Element getGeneratorElement(); + + void setGeneratorElement(Element element); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,705 @@ +/* + * 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.codewriter; + +import static com.oracle.truffle.dsl.processor.Utils.*; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.ast.*; + +public abstract class AbstractCodeWriter extends CodeElementScanner { + + private static final int LINE_LENGTH = 200; + private static final int LINE_WRAP_INDENTS = 3; + private static final String IDENT_STRING = " "; + private static final String LN = "\n"; /* unix style */ + + protected Writer writer; + private int indent; + private boolean newLine; + private int lineLength; + private boolean lineWrapping = false; + + private OrganizedImports imports; + + public void visitCompilationUnit(CodeCompilationUnit e) { + for (TypeElement clazz : e.getEnclosedElements()) { + clazz.accept(this, null); + } + } + + protected abstract Writer createWriter(CodeTypeElement clazz) throws IOException; + + @Override + public Void visitType(CodeTypeElement e, Void p) { + if (e.isTopLevelClass()) { + Writer w = null; + try { + imports = OrganizedImports.organize(e); + w = new TrimTrailingSpaceWriter(createWriter(e)); + writer = w; + writeRootClass(e); + } catch (IOException ex) { + throw new RuntimeException(ex); + } finally { + if (w != null) { + try { + w.close(); + } catch (Throwable e1) { + // see eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=361378 + // TODO temporary suppress errors on close. + } + } + writer = null; + } + } else { + writeClassImpl(e); + } + return null; + } + + private void writeRootClass(CodeTypeElement e) { + writeHeader(); + write("package ").write(e.getPackageName()).write(";").writeLn(); + writeEmptyLn(); + + Set generateImports = imports.generateImports(); + List typeImports = new ArrayList<>(); + List staticImports = new ArrayList<>(); + + for (CodeImport codeImport : generateImports) { + if (codeImport.isStaticImport()) { + staticImports.add(codeImport); + } else { + typeImports.add(codeImport); + } + } + Collections.sort(typeImports); + Collections.sort(staticImports); + + for (CodeImport imp : staticImports) { + imp.accept(this, null); + writeLn(); + } + if (!staticImports.isEmpty()) { + writeEmptyLn(); + } + + for (CodeImport imp : typeImports) { + imp.accept(this, null); + writeLn(); + } + if (!typeImports.isEmpty()) { + writeEmptyLn(); + } + + writeClassImpl(e); + } + + private String useImport(Element enclosedType, TypeMirror type) { + if (imports != null) { + return imports.createTypeReference(enclosedType, type); + } else { + return Utils.getSimpleName(type); + } + } + + private void writeClassImpl(CodeTypeElement e) { + for (AnnotationMirror annotation : e.getAnnotationMirrors()) { + visitAnnotation(e, annotation); + writeLn(); + } + + writeModifiers(e.getModifiers()); + if (e.getKind() == ElementKind.ENUM) { + write("enum "); + } else { + write("class "); + } + write(e.getSimpleName()); + if (e.getSuperclass() != null && !getQualifiedName(e.getSuperclass()).equals("java.lang.Object")) { + write(" extends ").write(useImport(e, e.getSuperclass())); + } + if (e.getImplements().size() > 0) { + write(" implements "); + for (int i = 0; i < e.getImplements().size(); i++) { + write(useImport(e, e.getImplements().get(i))); + if (i < e.getImplements().size() - 1) { + write(", "); + } + } + } + + write(" {").writeLn(); + writeEmptyLn(); + indent(1); + + List staticFields = getStaticFields(e); + List instanceFields = getInstanceFields(e); + + for (int i = 0; i < staticFields.size(); i++) { + VariableElement field = staticFields.get(i); + field.accept(this, null); + if (e.getKind() == ElementKind.ENUM && i < staticFields.size() - 1) { + write(","); + writeLn(); + } else { + write(";"); + writeLn(); + } + } + + if (staticFields.size() > 0) { + writeEmptyLn(); + } + + for (VariableElement field : instanceFields) { + field.accept(this, null); + write(";"); + writeLn(); + } + if (instanceFields.size() > 0) { + writeEmptyLn(); + } + + for (ExecutableElement method : ElementFilter.constructorsIn(e.getEnclosedElements())) { + method.accept(this, null); + } + + for (ExecutableElement method : getInstanceMethods(e)) { + method.accept(this, null); + } + + for (ExecutableElement method : getStaticMethods(e)) { + method.accept(this, null); + } + + for (TypeElement clazz : e.getInnerClasses()) { + clazz.accept(this, null); + } + + dedent(1); + write("}"); + writeEmptyLn(); + } + + private static List getStaticFields(CodeTypeElement clazz) { + List staticFields = new ArrayList<>(); + for (VariableElement field : clazz.getFields()) { + if (field.getModifiers().contains(Modifier.STATIC)) { + staticFields.add(field); + } + } + return staticFields; + } + + private static List getInstanceFields(CodeTypeElement clazz) { + List instanceFields = new ArrayList<>(); + for (VariableElement field : clazz.getFields()) { + if (!field.getModifiers().contains(Modifier.STATIC)) { + instanceFields.add(field); + } + } + return instanceFields; + } + + private static List getStaticMethods(CodeTypeElement clazz) { + List staticMethods = new ArrayList<>(); + for (ExecutableElement method : clazz.getMethods()) { + if (method.getModifiers().contains(Modifier.STATIC)) { + staticMethods.add(method); + } + } + return staticMethods; + } + + private static List getInstanceMethods(CodeTypeElement clazz) { + List instanceMethods = new ArrayList<>(); + for (ExecutableElement method : clazz.getMethods()) { + if (!method.getModifiers().contains(Modifier.STATIC)) { + instanceMethods.add(method); + } + } + return instanceMethods; + } + + @Override + public Void visitVariable(VariableElement f, Void p) { + Element parent = f.getEnclosingElement(); + + for (AnnotationMirror annotation : f.getAnnotationMirrors()) { + visitAnnotation(f, annotation); + write(" "); + } + + CodeTree init = null; + if (f instanceof CodeVariableElement) { + init = ((CodeVariableElement) f).getInit(); + } + + if (parent.getKind() == ElementKind.ENUM && f.getModifiers().contains(Modifier.STATIC)) { + write(f.getSimpleName()); + if (init != null) { + if (init != null) { + write("("); + init.acceptCodeElementScanner(this, p); + write(")"); + } + } + } else { + writeModifiers(f.getModifiers()); + write(useImport(f, f.asType())); + + if (f.getEnclosingElement().getKind() == ElementKind.METHOD) { + ExecutableElement method = (ExecutableElement) f.getEnclosingElement(); + if (method.isVarArgs() && method.getParameters().indexOf(f) == method.getParameters().size() - 1) { + write("..."); + } + } + + write(" "); + write(f.getSimpleName()); + if (init != null) { + write(" = "); + init.acceptCodeElementScanner(this, p); + } + } + return null; + } + + public void visitAnnotation(Element enclosedElement, AnnotationMirror e) { + write("@").write(useImport(enclosedElement, e.getAnnotationType())); + + if (!e.getElementValues().isEmpty()) { + write("("); + final ExecutableElement defaultElement = findExecutableElement(e.getAnnotationType(), "value"); + + Map values = e.getElementValues(); + if (defaultElement != null && values.size() == 1 && values.get(defaultElement) != null) { + visitAnnotationValue(enclosedElement, values.get(defaultElement)); + } else { + Set methodsSet = values.keySet(); + List methodsList = new ArrayList<>(); + for (ExecutableElement method : methodsSet) { + if (values.get(method) == null) { + continue; + } + methodsList.add(method); + } + + Collections.sort(methodsList, new Comparator() { + + @Override + public int compare(ExecutableElement o1, ExecutableElement o2) { + return o1.getSimpleName().toString().compareTo(o2.getSimpleName().toString()); + } + }); + + for (int i = 0; i < methodsList.size(); i++) { + ExecutableElement method = methodsList.get(i); + AnnotationValue value = values.get(method); + write(method.getSimpleName().toString()); + write(" = "); + visitAnnotationValue(enclosedElement, value); + + if (i < methodsList.size() - 1) { + write(", "); + } + } + } + + write(")"); + } + } + + public void visitAnnotationValue(Element enclosedElement, AnnotationValue e) { + e.accept(new AnnotationValueWriterVisitor(enclosedElement), null); + } + + private class AnnotationValueWriterVisitor extends AbstractAnnotationValueVisitor7 { + + private final Element enclosedElement; + + public AnnotationValueWriterVisitor(Element enclosedElement) { + this.enclosedElement = enclosedElement; + } + + @Override + public Void visitBoolean(boolean b, Void p) { + write(Boolean.toString(b)); + return null; + } + + @Override + public Void visitByte(byte b, Void p) { + write(Byte.toString(b)); + return null; + } + + @Override + public Void visitChar(char c, Void p) { + write(Character.toString(c)); + return null; + } + + @Override + public Void visitDouble(double d, Void p) { + write(Double.toString(d)); + return null; + } + + @Override + public Void visitFloat(float f, Void p) { + write(Float.toString(f)); + return null; + } + + @Override + public Void visitInt(int i, Void p) { + write(Integer.toString(i)); + return null; + } + + @Override + public Void visitLong(long i, Void p) { + write(Long.toString(i)); + return null; + } + + @Override + public Void visitShort(short s, Void p) { + write(Short.toString(s)); + return null; + } + + @Override + public Void visitString(String s, Void p) { + write("\""); + write(s); + write("\""); + return null; + } + + @Override + public Void visitType(TypeMirror t, Void p) { + write(useImport(enclosedElement, t)); + write(".class"); + return null; + } + + @Override + public Void visitEnumConstant(VariableElement c, Void p) { + write(useImport(enclosedElement, c.asType())); + write("."); + write(c.getSimpleName().toString()); + return null; + } + + @Override + public Void visitAnnotation(AnnotationMirror a, Void p) { + AbstractCodeWriter.this.visitAnnotation(enclosedElement, a); + return null; + } + + @Override + public Void visitArray(List vals, Void p) { + write("{"); + for (int i = 0; i < vals.size(); i++) { + AnnotationValue value = vals.get(i); + AbstractCodeWriter.this.visitAnnotationValue(enclosedElement, value); + if (i < vals.size() - 1) { + write(", "); + } + } + write("}"); + return null; + } + } + + public ExecutableElement findExecutableElement(DeclaredType type, String name) { + List elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements()); + for (ExecutableElement executableElement : elements) { + if (executableElement.getSimpleName().toString().equals(name)) { + return executableElement; + } + } + return null; + } + + @Override + public void visitImport(CodeImport e, Void p) { + if (e.isStaticImport()) { + write("import static ").write(e.getImportString()).write(";"); + } else { + write("import ").write(e.getImportString()).write(";"); + } + } + + @Override + public Void visitExecutable(CodeExecutableElement e, Void p) { + for (AnnotationMirror annotation : e.getAnnotationMirrors()) { + visitAnnotation(e, annotation); + writeLn(); + } + + writeModifiers(e.getModifiers()); + + if (e.getReturnType() != null) { + write(useImport(e, e.getReturnType())); + write(" "); + } + write(e.getSimpleName()); + write("("); + + for (int i = 0; i < e.getParameters().size(); i++) { + VariableElement param = e.getParameters().get(i); + param.accept(this, p); + if (i < e.getParameters().size() - 1) { + write(", "); + } + } + write(")"); + + List throwables = e.getThrownTypes(); + if (throwables.size() > 0) { + write(" throws "); + for (int i = 0; i < throwables.size(); i++) { + write(useImport(e, throwables.get(i))); + if (i < throwables.size() - 1) { + write(", "); + } + } + } + + if (e.getModifiers().contains(Modifier.ABSTRACT)) { + writeLn(";"); + } else if (e.getBodyTree() != null) { + writeLn(" {"); + indent(1); + e.getBodyTree().acceptCodeElementScanner(this, p); + dedent(1); + writeLn("}"); + } else if (e.getBody() != null) { + write(" {"); + write(e.getBody()); + writeLn("}"); + } else { + writeLn("{ }"); + } + writeEmptyLn(); + return null; + } + + @Override + public void visitTree(CodeTree e, Void p) { + CodeTreeKind kind = e.getCodeKind(); + + switch (kind) { + case COMMA_GROUP: + List children = e.getEnclosedElements(); + for (int i = 0; i < children.size(); i++) { + children.get(i).acceptCodeElementScanner(this, p); + if (i < e.getEnclosedElements().size() - 1) { + write(", "); + } + } + break; + case GROUP: + for (CodeTree tree : e.getEnclosedElements()) { + tree.acceptCodeElementScanner(this, p); + } + break; + case INDENT: + indent(1); + for (CodeTree tree : e.getEnclosedElements()) { + tree.acceptCodeElementScanner(this, p); + } + dedent(1); + break; + case NEW_LINE: + writeLn(); + break; + case STRING: + if (e.getString() != null) { + write(e.getString()); + } else { + write("null"); + } + break; + case STATIC_FIELD_REFERENCE: + if (e.getString() != null) { + write(imports.createStaticFieldReference(e, e.getType(), e.getString())); + } else { + write("null"); + } + break; + case STATIC_METHOD_REFERENCE: + if (e.getString() != null) { + write(imports.createStaticMethodReference(e, e.getType(), e.getString())); + } else { + write("null"); + } + break; + case TYPE: + write(useImport(e, e.getType())); + break; + default: + assert false; + return; + } + } + + protected void writeHeader() { + // default implementation does nothing + } + + private void writeModifiers(Set modifiers) { + if (modifiers != null) { + for (Modifier modifier : modifiers) { + write(modifier.toString()); + write(" "); + } + } + } + + protected void indent(int count) { + indent += count; + } + + protected void dedent(int count) { + indent -= count; + } + + protected void writeLn() { + writeLn(""); + } + + protected void writeLn(String text) { + write(text); + write(LN); + lineLength = 0; + newLine = true; + if (lineWrapping) { + dedent(LINE_WRAP_INDENTS); + lineWrapping = false; + } + lineWrapping = false; + } + + protected void writeEmptyLn() { + writeLn(); + } + + private AbstractCodeWriter write(Name name) { + return write(name.toString()); + } + + private AbstractCodeWriter write(String m) { + try { + lineLength += m.length(); + if (newLine && m != LN) { + writeIndent(); + newLine = false; + } + if (lineLength > LINE_LENGTH && m.length() > 0) { + char firstChar = m.charAt(0); + if (Character.isAlphabetic(firstChar)) { + if (!lineWrapping) { + indent(LINE_WRAP_INDENTS); + } + lineWrapping = true; + lineLength = 0; + write(LN); + writeIndent(); + } + } + writer.write(m); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + private void writeIndent() throws IOException { + for (int i = 0; i < indent; i++) { + lineLength += IDENT_STRING.length(); + writer.write(IDENT_STRING); + } + } + + private static class TrimTrailingSpaceWriter extends Writer { + + private final Writer delegate; + private final StringBuilder buffer = new StringBuilder(); + + public TrimTrailingSpaceWriter(Writer delegate) { + this.delegate = delegate; + } + + @Override + public void close() throws IOException { + this.delegate.close(); + } + + @Override + public void flush() throws IOException { + this.delegate.flush(); + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + buffer.append(cbuf, off, len); + int newLinePoint = buffer.indexOf(LN); + + if (newLinePoint != -1) { + String lhs = trimTrailing(buffer.substring(0, newLinePoint)); + delegate.write(lhs); + delegate.write(LN); + buffer.delete(0, newLinePoint + 1); + } + } + + private static String trimTrailing(String s) { + int cut = 0; + for (int i = s.length() - 1; i >= 0; i--) { + if (Character.isWhitespace(s.charAt(i))) { + cut++; + } else { + break; + } + } + if (cut > 0) { + return s.substring(0, s.length() - cut); + } + return s; + } + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/FixWarningsVisitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/FixWarningsVisitor.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,128 @@ +/* + * 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.codewriter; + +import static com.oracle.truffle.dsl.processor.Utils.*; +import static javax.lang.model.element.Modifier.*; + +import java.io.*; +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.ast.*; + +public class FixWarningsVisitor extends CodeElementScanner { + + private final Set symbolsUsed = new HashSet<>(); + + private final ProcessorContext context; + private final DeclaredType unusedAnnotation; + private final DeclaredType overrideType; + + public FixWarningsVisitor(ProcessorContext context, DeclaredType unusedAnnotation, DeclaredType overrideType) { + this.context = context; + this.unusedAnnotation = unusedAnnotation; + this.overrideType = overrideType; + } + + @Override + public Void visitType(CodeTypeElement e, Void p) { + List superTypes = Utils.getSuperTypes(e); + for (TypeElement type : superTypes) { + String qualifiedName = Utils.getQualifiedName(type); + if (qualifiedName.equals(Serializable.class.getCanonicalName())) { + if (!e.containsField("serialVersionUID")) { + e.add(new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), context.getType(long.class), "serialVersionUID", "1L")); + } + break; + } + } + + return super.visitType(e, p); + } + + @Override + public Void visitExecutable(CodeExecutableElement e, Void p) { + if (e.getParameters().isEmpty()) { + return null; + } else if (e.getModifiers().contains(Modifier.ABSTRACT)) { + return null; + } else if (containsOverride(e)) { + return null; + } + + symbolsUsed.clear(); + super.visitExecutable(e, p); + if (e.getBodyTree() == null && e.getBody() != null) { + computeSymbols(e.getBody()); + } + + for (VariableElement parameter : e.getParameters()) { + if (!symbolsUsed.contains(parameter.getSimpleName().toString())) { + e.getAnnotationMirrors().add(createUnusedAnnotationMirror()); + break; + } + } + return null; + } + + private boolean containsOverride(CodeExecutableElement e) { + for (AnnotationMirror mirror : e.getAnnotationMirrors()) { + if (Utils.typeEquals(overrideType, mirror.getAnnotationType())) { + return true; + } + } + return false; + } + + private CodeAnnotationMirror createUnusedAnnotationMirror() { + CodeAnnotationMirror mirror = new CodeAnnotationMirror(unusedAnnotation); + mirror.setElementValue(mirror.findExecutableElement("value"), new CodeAnnotationValue("unused")); + return mirror; + } + + @Override + public void visitTree(CodeTree e, Void p) { + if (e.getString() != null) { + computeSymbols(e.getString()); + } + super.visitTree(e, p); + } + + private void computeSymbols(String s) { + // TODO there should not be any need for a StringTokenizer if we have a real AST for + // method bodies. Also the current solution is not perfect. What if one token + // is spread across multiple CodeTree instances? But for now that works. + StringTokenizer tokenizer = new StringTokenizer(s, ".= :,()[];{}\"\"'' ", false); + while (tokenizer.hasMoreElements()) { + String token = tokenizer.nextToken().trim(); + if (token.length() > 0) { + symbolsUsed.add(token); + } + } + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/GenerateOverrideVisitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/GenerateOverrideVisitor.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,61 @@ +/* + * 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.codewriter; + +import static com.oracle.truffle.dsl.processor.Utils.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.ast.*; + +public class GenerateOverrideVisitor extends CodeElementScanner { + + private final DeclaredType overrideType; + + public GenerateOverrideVisitor(DeclaredType overrideType) { + this.overrideType = overrideType; + } + + @Override + public Void visitExecutable(CodeExecutableElement e, Void p) { + if (!e.getModifiers().contains(Modifier.STATIC) && !e.getModifiers().contains(Modifier.PRIVATE)) { + String name = e.getSimpleName().toString(); + TypeMirror[] params = e.getParameterTypes(); + + for (AnnotationMirror mirror : e.getAnnotationMirrors()) { + if (Utils.typeEquals(overrideType, mirror.getAnnotationType())) { + // already declared (may happen if method copied from super class) + return super.visitExecutable(e, p); + } + } + + if (isDeclaredMethodInSuperType(e.getEnclosingClass(), name, params)) { + e.addAnnotationMirror(new CodeAnnotationMirror(overrideType)); + } + } + return super.visitExecutable(e, p); + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/OrganizedImports.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,491 @@ +/* + * 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.codewriter; + +import static com.oracle.truffle.dsl.processor.Utils.*; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.ast.*; + +public final class OrganizedImports { + + private final Set staticImportUsage = new HashSet<>(); + + private final Map simpleNamesUsed = new HashMap<>(); + + private final Set declaredStaticMethods = new HashSet<>(); + private final Set declaredStaticFields = new HashSet<>(); + private final Set ambiguousStaticMethods = new HashSet<>(); + private final Set ambiguousStaticFields = new HashSet<>(); + + private final CodeTypeElement topLevelClass; + + private OrganizedImports(CodeTypeElement topLevelClass) { + this.topLevelClass = topLevelClass; + } + + public static OrganizedImports organize(CodeTypeElement topLevelClass) { + OrganizedImports organized = new OrganizedImports(topLevelClass); + organized.organizeImpl(); + return organized; + } + + private void organizeImpl() { + ImportTypeReferenceVisitor reference = new ImportTypeReferenceVisitor(); + topLevelClass.accept(reference, null); + + processStaticImports(topLevelClass); + List types = Utils.getSuperTypes(topLevelClass); + for (TypeElement typeElement : types) { + processStaticImports(typeElement); + } + + for (TypeMirror type : staticImportUsage) { + TypeElement element = fromTypeMirror(type); + if (element != null) { + // already processed by supertype + if (types.contains(element)) { + continue; + } + processStaticImports(element); + } + } + } + + public String createTypeReference(Element enclosedElement, TypeMirror type) { + switch (type.getKind()) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case SHORT: + case INT: + case LONG: + case VOID: + return Utils.getSimpleName(type); + case DECLARED: + return createDeclaredTypeName(enclosedElement, (DeclaredType) type); + case ARRAY: + return createTypeReference(enclosedElement, ((ArrayType) type).getComponentType()) + "[]"; + case WILDCARD: + return createWildcardName(enclosedElement, (WildcardType) type); + case TYPEVAR: + return "?"; + default: + throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type); + } + } + + public String createStaticFieldReference(Element enclosedElement, TypeMirror type, String fieldName) { + return createStaticReference(enclosedElement, type, fieldName, ambiguousStaticFields, declaredStaticFields); + } + + public String createStaticMethodReference(Element enclosedElement, TypeMirror type, String methodName) { + return createStaticReference(enclosedElement, type, methodName, ambiguousStaticMethods, declaredStaticMethods); + } + + private String createStaticReference(Element enclosedElement, TypeMirror type, String name, Set ambiguousSymbols, Set declaredSymbols) { + if (ambiguousSymbols.contains(name)) { + // ambiguous import + return createTypeReference(enclosedElement, type) + "." + name; + } else if (!declaredSymbols.contains(name)) { + // not imported at all + return createTypeReference(enclosedElement, type) + "." + name; + } else { + // import declared and not ambiguous + return name; + } + } + + private String createWildcardName(Element enclosedElement, WildcardType type) { + StringBuilder b = new StringBuilder(); + if (type.getExtendsBound() != null) { + b.append("? extends ").append(createTypeReference(enclosedElement, type.getExtendsBound())); + } else if (type.getSuperBound() != null) { + b.append("? super ").append(createTypeReference(enclosedElement, type.getExtendsBound())); + } + return b.toString(); + } + + private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) { + String name = type.asElement().getSimpleName().toString(); + + if (needsImport(enclosedElement, type)) { + TypeMirror usedByType = simpleNamesUsed.get(name); + if (usedByType == null) { + simpleNamesUsed.put(name, type); + usedByType = type; + } + + if (!typeEquals(type, usedByType)) { + name = getQualifiedName(type); + } + } + + if (type.getTypeArguments().size() == 0) { + return name; + } + + StringBuilder b = new StringBuilder(name); + b.append("<"); + if (type.getTypeArguments().size() > 0) { + for (int i = 0; i < type.getTypeArguments().size(); i++) { + b.append(createTypeReference(enclosedElement, type.getTypeArguments().get(i))); + if (i < type.getTypeArguments().size() - 1) { + b.append(", "); + } + } + } + b.append(">"); + return b.toString(); + } + + public Set generateImports() { + Set imports = new HashSet<>(); + + imports.addAll(generateImports(simpleNamesUsed.values())); + imports.addAll(generateStaticImports(staticImportUsage)); + + return imports; + } + + boolean processStaticImports(TypeElement element) { + Set importedMethods = new HashSet<>(); + List methods = ElementFilter.methodsIn(element.getEnclosedElements()); + for (ExecutableElement method : methods) { + if (method.getModifiers().contains(Modifier.STATIC)) { + importedMethods.add(method.getSimpleName().toString()); + } + } + + boolean allMethodsAmbiguous = processStaticImportElements(importedMethods, this.ambiguousStaticMethods, this.declaredStaticMethods); + + Set importedFields = new HashSet<>(); + List fields = ElementFilter.fieldsIn(element.getEnclosedElements()); + for (VariableElement field : fields) { + if (field.getModifiers().contains(Modifier.STATIC)) { + importedFields.add(field.getSimpleName().toString()); + } + } + + boolean allFieldsAmbiguous = processStaticImportElements(importedFields, this.ambiguousStaticFields, this.declaredStaticFields); + + return allMethodsAmbiguous && allFieldsAmbiguous; + } + + private static boolean processStaticImportElements(Set newElements, Set ambiguousElements, Set declaredElements) { + boolean allAmbiguous = false; + if (declaredElements.containsAll(newElements)) { + // all types already declared -> we can remove the import completely -> they will all + // get ambiguous + allAmbiguous = true; + } + Set newAmbiguous = new HashSet<>(); + Set newDeclared = new HashSet<>(); + + for (String newElement : newElements) { + if (declaredElements.contains(newElement)) { + newAmbiguous.add(newElement); + } else if (ambiguousElements.contains(newElement)) { + // nothing to do + } else { + newDeclared.add(newElement); + } + } + + ambiguousElements.addAll(newAmbiguous); + declaredElements.addAll(newDeclared); + return allAmbiguous; + } + + private boolean needsImport(Element enclosedElement, TypeMirror importType) { + String importPackagName = getPackageName(importType); + if (importPackagName == null) { + return false; + } else if (importPackagName.equals("java.lang")) { + return false; + } else if (importPackagName.equals(getPackageName(topLevelClass)) && Utils.isTopLevelClass(importType)) { + return false; // same package name -> no import + } + + List elements = Utils.getElementHierarchy(enclosedElement); + + Set autoImportedTypes = new HashSet<>(); + for (Element element : elements) { + if (element.getKind().isClass()) { + collectSuperTypeImports((TypeElement) element, autoImportedTypes); + collectInnerTypeImports((TypeElement) element, autoImportedTypes); + } + } + + String qualifiedName = getQualifiedName(importType); + if (autoImportedTypes.contains(qualifiedName)) { + return false; + } + + return true; + } + + private static Set generateImports(Collection toGenerate) { + TreeSet importObjects = new TreeSet<>(); + for (TypeMirror importType : toGenerate) { + importObjects.add(new CodeImport(importType, getQualifiedName(importType), false)); + } + return importObjects; + } + + private static void collectInnerTypeImports(TypeElement e, Set autoImportedTypes) { + autoImportedTypes.add(getQualifiedName(e)); + for (TypeElement innerClass : ElementFilter.typesIn(e.getEnclosedElements())) { + collectInnerTypeImports(innerClass, autoImportedTypes); + } + } + + private static void collectSuperTypeImports(TypeElement e, Set autoImportedTypes) { + List superTypes = getSuperTypes(e); + for (TypeElement superType : superTypes) { + List declaredTypes = getDeclaredTypes(superType); + for (TypeElement declaredType : declaredTypes) { + autoImportedTypes.add(getQualifiedName(declaredType)); + } + } + } + + private Set generateStaticImports(Set toGenerate) { + Set autoImportedStaticTypes = new HashSet<>(); + + // if type is declared inside a super type of this class -> no import + autoImportedStaticTypes.add(getQualifiedName(topLevelClass)); + autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(topLevelClass)); + + TreeSet importObjects = new TreeSet<>(); + for (TypeMirror importType : toGenerate) { + if (getPackageName(importType) == null) { + continue; // no package name -> no import + } + + String qualifiedName = getQualifiedName(importType); + if (autoImportedStaticTypes.contains(qualifiedName)) { + continue; + } + + importObjects.add(new CodeImport(importType, qualifiedName + ".*", true)); + } + + return importObjects; + } + + private abstract static class TypeReferenceVisitor extends CodeElementScanner { + + @Override + public void visitTree(CodeTree e, Void p) { + if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) { + visitStaticFieldReference(e, e.getType(), e.getString()); + } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) { + visitStaticMethodReference(e, e.getType(), e.getString()); + } else if (e.getType() != null) { + visitTypeReference(e, e.getType()); + } + super.visitTree(e, p); + } + + @Override + public Void visitExecutable(CodeExecutableElement e, Void p) { + visitAnnotations(e, e.getAnnotationMirrors()); + if (e.getReturnType() != null) { + visitTypeReference(e, e.getReturnType()); + } + for (TypeMirror type : e.getThrownTypes()) { + visitTypeReference(e, type); + } + return super.visitExecutable(e, p); + } + + @Override + public Void visitType(CodeTypeElement e, Void p) { + visitAnnotations(e, e.getAnnotationMirrors()); + + visitTypeReference(e, e.getSuperclass()); + for (TypeMirror type : e.getImplements()) { + visitTypeReference(e, type); + } + + return super.visitType(e, p); + } + + private void visitAnnotations(Element enclosingElement, List mirrors) { + for (AnnotationMirror mirror : mirrors) { + visitAnnotation(enclosingElement, mirror); + } + } + + public void visitAnnotation(Element enclosingElement, AnnotationMirror e) { + visitTypeReference(enclosingElement, e.getAnnotationType()); + if (!e.getElementValues().isEmpty()) { + Map values = e.getElementValues(); + Set methodsSet = values.keySet(); + List methodsList = new ArrayList<>(); + for (ExecutableElement method : methodsSet) { + if (values.get(method) == null) { + continue; + } + methodsList.add(method); + } + + for (int i = 0; i < methodsList.size(); i++) { + AnnotationValue value = values.get(methodsList.get(i)); + visitAnnotationValue(enclosingElement, value); + } + } + } + + public void visitAnnotationValue(Element enclosingElement, AnnotationValue e) { + e.accept(new AnnotationValueReferenceVisitor(enclosingElement), null); + } + + private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7 { + + private final Element enclosingElement; + + public AnnotationValueReferenceVisitor(Element enclosedElement) { + this.enclosingElement = enclosedElement; + } + + @Override + public Void visitBoolean(boolean b, Void p) { + return null; + } + + @Override + public Void visitByte(byte b, Void p) { + return null; + } + + @Override + public Void visitChar(char c, Void p) { + return null; + } + + @Override + public Void visitDouble(double d, Void p) { + return null; + } + + @Override + public Void visitFloat(float f, Void p) { + return null; + } + + @Override + public Void visitInt(int i, Void p) { + return null; + } + + @Override + public Void visitLong(long i, Void p) { + return null; + } + + @Override + public Void visitShort(short s, Void p) { + return null; + } + + @Override + public Void visitString(String s, Void p) { + return null; + } + + @Override + public Void visitType(TypeMirror t, Void p) { + visitTypeReference(enclosingElement, t); + return null; + } + + @Override + public Void visitEnumConstant(VariableElement c, Void p) { + visitTypeReference(enclosingElement, c.asType()); + return null; + } + + @Override + public Void visitAnnotation(AnnotationMirror a, Void p) { + TypeReferenceVisitor.this.visitAnnotation(enclosingElement, a); + return null; + } + + @Override + public Void visitArray(List vals, Void p) { + for (int i = 0; i < vals.size(); i++) { + TypeReferenceVisitor.this.visitAnnotationValue(enclosingElement, vals.get(i)); + } + return null; + } + } + + @Override + public Void visitVariable(VariableElement f, Void p) { + visitAnnotations(f, f.getAnnotationMirrors()); + visitTypeReference(f, f.asType()); + return super.visitVariable(f, p); + } + + @Override + public void visitImport(CodeImport e, Void p) { + } + + public abstract void visitTypeReference(Element enclosedType, TypeMirror type); + + public abstract void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName); + + public abstract void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName); + + } + + private class ImportTypeReferenceVisitor extends TypeReferenceVisitor { + + @Override + public void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName) { + staticImportUsage.add(type); + } + + @Override + public void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName) { + staticImportUsage.add(type); + } + + @Override + public void visitTypeReference(Element enclosedType, TypeMirror type) { + createTypeReference(enclosedType, type); + } + + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/AbstractCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/AbstractCompiler.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,67 @@ +/* + * 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.compiler; + +import java.lang.reflect.*; + +public abstract class AbstractCompiler implements Compiler { + + protected static Object method(Object o, String methodName) throws Exception { + Method method = o.getClass().getMethod(methodName); + method.setAccessible(true); + return method.invoke(o); + } + + protected static Object method(Object o, String methodName, Class[] paramTypes, Object... values) throws Exception { + Method method = o.getClass().getMethod(methodName, paramTypes); + method.setAccessible(true); + return method.invoke(o, values); + } + + protected static Object field(Object o, String fieldName) throws Exception { + if (o == null) { + return null; + } + Field field = o.getClass().getField(fieldName); + field.setAccessible(true); + return field.get(o); + } + + protected static String parseHeader(String content) { + int index = content.indexOf("/*"); + if (index == -1) { + return null; + } + if (!content.substring(0, index).trim().equals("")) { + // just whitespace before + return null; + } + + int endIndex = content.indexOf("*/", index); + if (endIndex == -1) { + return null; + } + return content.substring(index, endIndex + 2); + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/Compiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/Compiler.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,34 @@ +/* + * 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.compiler; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; + +public interface Compiler { + + String getMethodBody(ProcessingEnvironment env, ExecutableElement method); + + String getHeaderComment(ProcessingEnvironment env, Element type); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/CompilerFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/CompilerFactory.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,48 @@ +/* + * 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.compiler; + +import javax.lang.model.element.*; + +public class CompilerFactory { + + private static Compiler javac; + private static Compiler jdt; + + public static Compiler getCompiler(Element currentElement) { + if (JavaCCompiler.isValidElement(currentElement)) { + if (javac == null) { + javac = new JavaCCompiler(); + } + return javac; + } else if (JDTCompiler.isValidElement(currentElement)) { + if (jdt == null) { + jdt = new JDTCompiler(); + } + return jdt; + } else { + throw new UnsupportedOperationException("Unsupported compiler for element " + currentElement.getClass().getName() + "."); + } + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JDTCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JDTCompiler.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,109 @@ +/* + * 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.compiler; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.*; + +public class JDTCompiler extends AbstractCompiler { + + public static boolean isValidElement(Element currentElement) { + try { + Class elementClass = Class.forName("org.eclipse.jdt.internal.compiler.apt.model.ElementImpl"); + return elementClass.isAssignableFrom(currentElement.getClass()); + } catch (ClassNotFoundException e) { + return false; + } + } + + @Override + public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { + try { + + char[] source = getSource(method); + if (source == null) { + return null; + } + + /* + * AbstractMethodDeclaration decl = + * ((MethodBinding)(((ElementImpl)method)._binding)).sourceMethod(); int bodyStart = + * decl.bodyStart; int bodyEnd = decl.bodyEnd; + */ + Object decl = method(field(method, "_binding"), "sourceMethod"); + int bodyStart = (int) field(decl, "bodyStart"); + int bodyEnd = (int) field(decl, "bodyEnd"); + + int length = bodyEnd - bodyStart; + char[] target = new char[length]; + System.arraycopy(source, bodyStart, target, 0, length); + + return new String(target); + } catch (Exception e) { + return Utils.printException(e); + } + } + + private static char[] getSource(Element element) throws Exception { + /* + * Binding binding = ((ElementImpl)element)._binding; char[] source = null; if (binding + * instanceof MethodBinding) { source = ((MethodBinding) + * binding).sourceMethod().compilationResult.getCompilationUnit().getContents(); } else if + * (binding instanceof SourceTypeBinding) { source = + * ((SourceTypeBinding)binding).scope.referenceContext + * .compilationResult.compilationUnit.getContents(); } return source; + */ + + Object binding = field(element, "_binding"); + Class methodBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.MethodBinding"); + Class referenceBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding"); + + char[] source = null; + if (methodBindingClass.isAssignableFrom(binding.getClass())) { + Object sourceMethod = method(binding, "sourceMethod"); + if (sourceMethod == null) { + return null; + } + source = (char[]) method(method(field(sourceMethod, "compilationResult"), "getCompilationUnit"), "getContents"); + } else if (referenceBindingClass.isAssignableFrom(binding.getClass())) { + source = (char[]) method(field(field(field(field(binding, "scope"), "referenceContext"), "compilationResult"), "compilationUnit"), "getContents"); + } + return source; + } + + @Override + public String getHeaderComment(ProcessingEnvironment env, Element type) { + try { + char[] source = getSource(type); + if (source == null) { + return null; + } + return parseHeader(new String(source)); + } catch (Exception e) { + return Utils.printException(e); + } + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JavaCCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JavaCCompiler.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,91 @@ +/* + * 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.compiler; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.*; + +public class JavaCCompiler extends AbstractCompiler { + + public static boolean isValidElement(Element currentElement) { + try { + Class elementClass = Class.forName("com.sun.tools.javac.code.Symbol"); + return elementClass.isAssignableFrom(currentElement.getClass()); + } catch (ClassNotFoundException e) { + return false; + } + } + + private static final Class[] getTreeAndTopLevelSignature = new Class[]{Element.class, AnnotationMirror.class, AnnotationValue.class}; + private static final Class[] getCharContentSignature = new Class[]{boolean.class}; + + @Override + public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { + try { + /* + * if (false) { Pair treeAndTopLevel = ((JavacElements) + * env.getElementUtils()).getTreeAndTopLevel(method, null, null); JCBlock block = + * ((JCMethodDecl) treeAndTopLevel.fst).getBody(); int startPos = block.pos; int endPos + * = block.endpos; String methodBody = + * treeAndTopLevel.snd.getSourceFile().getCharContent(true).subSequence(startPos + 1, + * endPos).toString(); return methodBody; } + */ + + Object treeAndTopLevel = getTreeAndTopLevel(env, method); + Object block = method(field(treeAndTopLevel, "fst"), "getBody"); + int startPos = (int) field(block, "pos"); + int endPos = (int) field(block, "endpos"); + return getContent(treeAndTopLevel).subSequence(startPos + 1, endPos).toString(); + } catch (Exception e) { + return Utils.printException(e); + } + } + + private static CharSequence getContent(Object treeAndTopLevel) throws Exception { + /* + * CharSequence content = treeAndTopLevel.snd.getSourceFile().getCharContent(true); + */ + return (CharSequence) method(method(field(treeAndTopLevel, "snd"), "getSourceFile"), "getCharContent", getCharContentSignature, true); + } + + private static Object getTreeAndTopLevel(ProcessingEnvironment env, Element element) throws Exception { + /* + * Pair treeAndTopLevel = ((JavacElements) + * env.getElementUtils()).getTreeAndTopLevel(method, null, null); + */ + return method(method(env, "getElementUtils"), "getTreeAndTopLevel", getTreeAndTopLevelSignature, element, null, null); + } + + @Override + public String getHeaderComment(ProcessingEnvironment env, Element type) { + try { + String content = getContent(getTreeAndTopLevel(env, type)).toString(); + return parseHeader(content); + } catch (Exception e) { + return Utils.printException(e); + } + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastData.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/CreateCastData.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,42 @@ +/* + * 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.util.*; + +import com.oracle.truffle.dsl.processor.template.*; + +public class CreateCastData extends TemplateMethod { + + private final List childNames; + + public CreateCastData(TemplateMethod method, List childNames) { + super(method); + this.childNames = childNames; + } + + public List getChildNames() { + return childNames; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.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/CreateCastParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,113 @@ +/* + * 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 java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.template.*; + +public class CreateCastParser extends NodeMethodParser { + + public CreateCastParser(ProcessorContext context, NodeData operation) { + super(context, operation); + } + + @Override + public Class getAnnotationType() { + return CreateCast.class; + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + List childNames = Utils.getAnnotationValueList(String.class, mirror, "value"); + TypeMirror baseType = getContext().getTruffleTypes().getNode(); + for (String childName : childNames) { + NodeChildData child = getNode().findChild(childName); + if (child != null) { + baseType = child.getOriginalType(); + break; + } + } + MethodSpec spec = new MethodSpec(new InheritsParameterSpec(getContext(), "child", baseType)); + addDefaultFieldMethodSpec(method, spec); + spec.addRequired(new ParameterSpec("castedChild", baseType)).setSignature(true); + return spec; + } + + @Override + public CreateCastData create(TemplateMethod method) { + AnnotationMirror mirror = method.getMarkerAnnotation(); + List childNames = Utils.getAnnotationValueList(String.class, mirror, "value"); + CreateCastData cast = new CreateCastData(method, childNames); + AnnotationValue value = Utils.getAnnotationValue(mirror, "value"); + TypeMirror type = null; + if (childNames == null || childNames.isEmpty()) { + cast.addError(value, "No value specified but required."); + return cast; + } + + for (String childName : childNames) { + NodeChildData child = getNode().findChild(childName); + if (child == null) { + // error + cast.addError(value, "Specified child '%s' not found.", childName); + continue; + } + if (type == null) { + type = child.getNodeType(); + } else if (!Utils.typeEquals(type, child.getNodeType())) { + cast.addError(value, "All child nodes for a cast must have the same node type."); + continue; + } + } + return cast; + } + + private static class InheritsParameterSpec extends ParameterSpec { + + private final ProcessorContext context; + + public InheritsParameterSpec(ProcessorContext context, String name, TypeMirror... allowedTypes) { + super(name, Arrays.asList(allowedTypes)); + this.context = context; + } + + @Override + public boolean matches(TypeMirror actualType) { + boolean found = false; + for (TypeMirror specType : getAllowedTypes()) { + if (Utils.isAssignable(context, actualType, specType)) { + found = true; + break; + } + } + return found; + } + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeData.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/ExecutableTypeData.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,89 @@ +/* + * 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 javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.template.*; +import com.oracle.truffle.dsl.processor.typesystem.*; + +public class ExecutableTypeData extends TemplateMethod { + + private final TypeSystemData typeSystem; + private final TypeData type; + + public ExecutableTypeData(TemplateMethod method, ExecutableElement executable, TypeSystemData typeSystem, TypeData type) { + super(method, executable); + this.typeSystem = typeSystem; + this.type = type; + } + + public TypeData getType() { + return type; + } + + public TypeSystemData getTypeSystem() { + return typeSystem; + } + + public boolean hasFrame() { + return getMethod().getParameters().size() > 0; + } + + public boolean hasUnexpectedValue(ProcessorContext context) { + return Utils.canThrowType(getMethod().getThrownTypes(), context.getTruffleTypes().getUnexpectedValueException()); + } + + public boolean isFinal() { + return getMethod().getModifiers().contains(Modifier.FINAL); + } + + public boolean isAbstract() { + return getMethod().getModifiers().contains(Modifier.ABSTRACT); + } + + public int getEvaluatedCount() { + int count = 0; + for (ActualParameter parameter : getParameters()) { + if (parameter.getSpecification().isSignature()) { + count++; + } + } + return count; + } + + @Override + public int hashCode() { + return type.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ExecutableTypeData) { + return type.equals(((ExecutableTypeData) obj).type); + } + return super.equals(obj); + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.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/ExecutableTypeMethodParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,92 @@ +/* + * 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 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.NodeChildData.*; +import com.oracle.truffle.dsl.processor.template.*; +import com.oracle.truffle.dsl.processor.typesystem.*; + +public class ExecutableTypeMethodParser extends NodeMethodParser { + + public ExecutableTypeMethodParser(ProcessorContext context, NodeData node) { + super(context, node); + setEmitErrors(false); + setParseNullOnError(false); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null); + List requiredSpecs = new ArrayList<>(spec.getRequired()); + spec.getRequired().clear(); + + for (ParameterSpec originalSpec : requiredSpecs) { + spec.addRequired(new ParameterSpec(originalSpec, Arrays.asList(getNode().getTypeSystem().getGenericType()))); + } + + spec.setVariableRequiredArguments(true); + ParameterSpec other = new ParameterSpec("other", Arrays.asList(getNode().getTypeSystem().getGenericType())); + other.setCardinality(Cardinality.MANY); + other.setSignature(true); + other.setIndexed(true); + spec.addRequired(other); + return spec; + } + + @Override + public final boolean isParsable(ExecutableElement method) { + if (method.getModifiers().contains(Modifier.STATIC)) { + return false; + } else if (method.getModifiers().contains(Modifier.NATIVE)) { + return false; + } + return method.getSimpleName().toString().startsWith("execute"); + } + + @Override + protected List nodeTypeMirrors(NodeData nodeData) { + // executable types not yet available + List types = new ArrayList<>(nodeData.getTypeSystem().getPrimitiveTypeMirrors()); + types.add(nodeData.getTypeSystem().getVoidType().getPrimitiveType()); + return types; + } + + @Override + public ExecutableTypeData create(TemplateMethod method) { + TypeData resolvedType = method.getReturnType().getTypeSystemType(); + return new ExecutableTypeData(method, method.getMethod(), getNode().getTypeSystem(), resolvedType); + } + + @Override + public Class getAnnotationType() { + return null; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.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/GenericParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,74 @@ +/* + * 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 java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.template.*; + +public class GenericParser extends NodeMethodParser { + + public GenericParser(ProcessorContext context, NodeData node) { + super(context, node); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + return createDefaultMethodSpec(method, mirror, true, null); + } + + @Override + protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, int evaluatedCount) { + List execTypes = nodeData.findGenericExecutableTypes(getContext(), evaluatedCount); + List types = new ArrayList<>(); + for (ExecutableTypeData type : execTypes) { + types.add(type.getType().getPrimitiveType()); + } + ParameterSpec spec = new ParameterSpec(valueName, types); + spec.setSignature(true); + return spec; + } + + @Override + protected ParameterSpec createReturnParameterSpec() { + return super.createValueParameterSpec("returnValue", getNode(), 0); + } + + @Override + public SpecializationData create(TemplateMethod method) { + SpecializationData data = new SpecializationData(method, true, false, false); + return data; + } + + @Override + public Class getAnnotationType() { + return Generic.class; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.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/NodeChildData.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,161 @@ +/* + * 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 java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.template.*; +import com.oracle.truffle.dsl.processor.typesystem.*; + +public class NodeChildData extends MessageContainer { + + public enum Cardinality { + ONE, MANY; + + public boolean isMany() { + return this == MANY; + } + + public boolean isOne() { + return this == ONE; + } + } + + public enum ExecutionKind { + DEFAULT, SHORT_CIRCUIT + } + + private final Element sourceElement; + private final AnnotationMirror sourceAnnotationMirror; + + private final String name; + private final TypeMirror type; + private final TypeMirror originalType; + private final Element accessElement; + + private final Cardinality cardinality; + private final ExecutionKind executionKind; + + private List executeWith = Collections.emptyList(); + + private NodeData nodeData; + + public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality, + ExecutionKind executionKind) { + this.sourceElement = sourceElement; + this.sourceAnnotationMirror = sourceMirror; + this.name = name; + this.type = nodeType; + this.originalType = originalNodeType; + this.accessElement = accessElement; + this.cardinality = cardinality; + this.executionKind = executionKind; + } + + public List getExecuteWith() { + return executeWith; + } + + void setExecuteWith(List executeWith) { + this.executeWith = executeWith; + } + + public ExecutableTypeData findExecutableType(ProcessorContext context, TypeData targetType) { + ExecutableTypeData executableType = nodeData.findExecutableType(targetType, getExecuteWith().size()); + if (executableType == null) { + executableType = findAnyGenericExecutableType(context); + } + return executableType; + } + + public List findGenericExecutableTypes(ProcessorContext context) { + return nodeData.findGenericExecutableTypes(context, getExecuteWith().size()); + } + + public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) { + return nodeData.findAnyGenericExecutableType(context, getExecuteWith().size()); + } + + public List findExecutableTypes() { + return nodeData.getExecutableTypes(getExecuteWith().size()); + } + + public TypeMirror getOriginalType() { + return originalType; + } + + @Override + public Element getMessageElement() { + return sourceElement; + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return sourceAnnotationMirror; + } + + public boolean isShortCircuit() { + return executionKind == ExecutionKind.SHORT_CIRCUIT; + } + + void setNode(NodeData nodeData) { + this.nodeData = nodeData; + if (nodeData != null) { + getMessages().addAll(nodeData.collectMessages()); + } + } + + public Element getAccessElement() { + return accessElement; + } + + public TypeMirror getNodeType() { + return type; + } + + public Cardinality getCardinality() { + return cardinality; + } + + public ExecutionKind getExecutionKind() { + return executionKind; + } + + public NodeData getNodeData() { + return nodeData; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", execution=" + executionKind + ", node=" + getNodeData() + "]"; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.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/NodeCodeGenerator.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,2437 @@ +/* + * 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 static com.oracle.truffle.dsl.processor.Utils.*; +import static javax.lang.model.element.Modifier.*; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.nodes.NodeInfo.Kind; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.ast.*; +import com.oracle.truffle.dsl.processor.node.NodeChildData.*; +import com.oracle.truffle.dsl.processor.template.*; +import com.oracle.truffle.dsl.processor.typesystem.*; + +public class NodeCodeGenerator extends CompilationUnitFactory { + + private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; + + private static final String EXECUTE_GENERIC_NAME = "executeGeneric0"; + private static final String EXECUTE_SPECIALIZE_NAME = "executeAndSpecialize0"; + + public NodeCodeGenerator(ProcessorContext context) { + super(context); + } + + private TypeMirror getUnexpectedValueException() { + return getContext().getTruffleTypes().getUnexpectedValueException(); + } + + private static String factoryClassName(NodeData node) { + return node.getNodeId() + "Factory"; + } + + private static String nodeSpecializationClassName(SpecializationData specialization) { + String nodeid = specialization.getNode().getNodeId(); + if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { + nodeid = nodeid.substring(0, nodeid.length() - 4); + } + + String name = Utils.firstLetterUpperCase(nodeid); + name += Utils.firstLetterUpperCase(specialization.getId()); + name += "Node"; + return name; + } + + private static String nodePolymorphicClassName(NodeData node, SpecializationData specialization) { + String nodeid = node.getNodeId(); + if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { + nodeid = nodeid.substring(0, nodeid.length() - 4); + } + + String name = Utils.firstLetterUpperCase(nodeid); + int index = specialization == null ? 0 : node.getPolymorphicSpecializations().indexOf(specialization); + if (index == 0) { + name += "PolymorphicNode"; + } else { + name += "Polymorphic" + index + "Node"; + } + return name; + } + + private static String valueNameEvaluated(ActualParameter targetParameter) { + return valueName(targetParameter) + "Evaluated"; + } + + private static String valueName(ActualParameter param) { + return param.getLocalName(); + } + + private static String castValueName(ActualParameter parameter) { + return valueName(parameter) + "Cast"; + } + + 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")); + } + for (ActualParameter parameter : specialization.getParameters()) { + ParameterSpec spec = parameter.getSpecification(); + if (forceFrame && spec.getName().equals("frame")) { + continue; + } + if (spec.isLocal()) { + continue; + } + + String name = valueName(parameter); + if (evaluated && spec.isSignature()) { + name = valueNameEvaluated(parameter); + } + + method.addParameter(new CodeVariableElement(parameter.getType(), name)); + } + } + + private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeImplicit) { + if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { + builder.string("frameValue"); + } + for (ActualParameter parameter : specialization.getParameters()) { + ParameterSpec spec = parameter.getSpecification(); + if (forceFrame && spec.getName().equals("frame")) { + continue; + } + + if (!includeImplicit && (parameter.isImplicit())) { + continue; + } + if (parameter.getSpecification().isLocal()) { + continue; + } + + ActualParameter sourceParameter = source.findParameter(parameter.getLocalName()); + + if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) { + builder.cast(parameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); + } else if (sourceParameter != null) { + builder.string(valueName(sourceParameter, parameter)); + } else { + builder.string(valueName(parameter)); + } + } + } + + private String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) { + if (sourceParameter != null) { + if (!sourceParameter.getSpecification().isSignature()) { + return valueName(targetParameter); + } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) { + if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), targetParameter.getTypeSystemType())) { + return castValueName(targetParameter); + } + } + return valueName(targetParameter); + } else { + return valueName(targetParameter); + } + } + + private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName, + String... customSignatureValueNames) { + CodeTreeBuilder builder = parent.create(); + + boolean castedValues = sourceMethod != targetMethod; + + builder.startGroup(); + ExecutableElement method = targetMethod.getMethod(); + if (method == null) { + throw new UnsupportedOperationException(); + } + TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); + NodeData node = (NodeData) targetMethod.getTemplate(); + + if (target == null) { + boolean accessible = targetMethod.canBeAccessedByInstanceOf(getContext(), node.getNodeType()); + if (accessible) { + if (builder.findMethod().getModifiers().contains(STATIC)) { + if (method.getModifiers().contains(STATIC)) { + builder.type(targetClass.asType()); + } else { + builder.string(THIS_NODE_LOCAL_VAR_NAME); + } + } else { + if (targetMethod instanceof ExecutableTypeData) { + builder.string("this"); + } else { + builder.string("super"); + } + } + } else { + if (method.getModifiers().contains(STATIC)) { + builder.type(targetClass.asType()); + } else { + ActualParameter parameter = null; + for (ActualParameter searchParameter : targetMethod.getParameters()) { + if (searchParameter.getSpecification().isSignature()) { + parameter = searchParameter; + break; + } + } + ActualParameter sourceParameter = sourceMethod.findParameter(parameter.getLocalName()); + assert parameter != null; + + if (castedValues && sourceParameter != null) { + builder.string(valueName(sourceParameter, parameter)); + } else { + builder.string(valueName(parameter)); + } + } + } + builder.string("."); + } else { + builder.tree(target); + } + builder.startCall(method.getSimpleName().toString()); + + int signatureIndex = 0; + + for (ActualParameter targetParameter : targetMethod.getParameters()) { + ActualParameter valueParameter = null; + if (sourceMethod != null) { + valueParameter = sourceMethod.findParameter(targetParameter.getLocalName()); + } + if (valueParameter == null) { + valueParameter = targetParameter; + } + TypeData targetType = targetParameter.getTypeSystemType(); + + if (targetParameter.isImplicit() || valueParameter.isImplicit()) { + continue; + } + + TypeData valueType = null; + if (valueParameter != null) { + valueType = valueParameter.getTypeSystemType(); + } + + if (signatureIndex < customSignatureValueNames.length && targetParameter.getSpecification().isSignature()) { + builder.string(customSignatureValueNames[signatureIndex]); + signatureIndex++; + } else if (targetParameter.getSpecification().isLocal()) { + builder.startGroup(); + if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) { + builder.string(THIS_NODE_LOCAL_VAR_NAME).string("."); + } else { + builder.string("this."); + } + builder.string(targetParameter.getSpecification().getName()); + builder.end(); + } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) { + builder.string("ex.getResult()"); + } else if (targetType == null || targetType.isGeneric() || (valueType != null && valueType.equalsType(targetType))) { + builder.startGroup(); + + if (valueType != null && sourceMethod.getMethodName().equals(targetMethod.getMethodName()) && !valueType.isGeneric() && targetType.isGeneric()) { + builder.string("("); + builder.type(targetType.getPrimitiveType()); + builder.string(") "); + } + builder.string(valueName(targetParameter)); + builder.end(); + } else { + builder.string(castValueName(targetParameter)); + } + } + + builder.end().end(); + + return builder.getRoot(); + } + + private static String baseClassName(NodeData node) { + String nodeid = node.getNodeId(); + if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { + nodeid = nodeid.substring(0, nodeid.length() - 4); + } + String name = Utils.firstLetterUpperCase(nodeid); + name += "BaseNode"; + return name; + } + + private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, CodeTree value) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + startCallTypeSystemMethod(context, builder, node, methodName); + builder.tree(value); + builder.end().end(); + return builder.getRoot(); + } + + private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, NodeData node, String methodName) { + VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, node.getTypeSystem()); + assert singleton != null; + + body.startGroup(); + body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString()); + body.string(".").startCall(methodName); + } + + private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData sourceSpecialization, SpecializationData targetSpecialization, boolean castValues, + CodeTree guardedStatements, CodeTree elseStatements, boolean emitAssumptions, boolean forceElse) { + + NodeData node = targetSpecialization.getNode(); + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, sourceSpecialization, targetSpecialization, emitAssumptions); + CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, sourceSpecialization, targetSpecialization); + + Set valuesNeedsCast; + if (castValues) { + // cast all + valuesNeedsCast = null; + } else { + // find out which values needs a cast + valuesNeedsCast = new HashSet<>(); + for (GuardData guard : targetSpecialization.getGuards()) { + for (ActualParameter targetParameter : guard.getParameters()) { + NodeChildData field = node.findChild(targetParameter.getSpecification().getName()); + if (field == null) { + continue; + } + TypeData targetType = targetParameter.getTypeSystemType(); + ActualParameter sourceParameter = sourceSpecialization.findParameter(targetParameter.getLocalName()); + if (sourceParameter == null) { + sourceParameter = targetParameter; + } + TypeData sourceType = sourceParameter.getTypeSystemType(); + + if (sourceType.needsCastTo(getContext(), targetType)) { + valuesNeedsCast.add(targetParameter.getLocalName()); + } + } + } + } + + int ifCount = 0; + + if (implicitGuards != null) { + builder.startIf(); + builder.tree(implicitGuards); + builder.end(); + builder.startBlock(); + ifCount++; + } + + builder.tree(createCasts(parent, valuesNeedsCast, sourceSpecialization, targetSpecialization)); + + if (explicitGuards != null) { + builder.startIf(); + builder.tree(explicitGuards); + builder.end(); + builder.startBlock(); + ifCount++; + } + + if (implicitGuards == null && explicitGuards == null && conditionPrefix != null && !conditionPrefix.isEmpty()) { + builder.startIf(); + builder.string(conditionPrefix); + builder.end().startBlock(); + ifCount++; + } + + builder.tree(guardedStatements); + + builder.end(ifCount); + if (elseStatements != null && (forceElse || ifCount > 0)) { + builder.tree(elseStatements); + } + return builder.getRoot(); + } + + private CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, TemplateMethod valueSpecialization, SpecializationData guardedSpecialization) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; + if (guardedSpecialization.getGuards().size() > 0) { + // Explicitly specified guards + for (GuardData guard : guardedSpecialization.getGuards()) { + builder.string(andOperator); + builder.tree(createTemplateMethodCall(parent, null, valueSpecialization, guard, null)); + andOperator = " && "; + } + } + + return builder.isEmpty() ? null : builder.getRoot(); + } + + private CodeTree createCasts(CodeTreeBuilder parent, Set castWhiteList, TemplateMethod valueSpecialization, SpecializationData guardedSpecialization) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + // Implict guards based on method signature + for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { + NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName()); + if (field == null) { + continue; + } + ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); + + if (valueParam == null) { + /* + * If used inside a function execute method. The value param may not exist. In that + * case it assumes that the value is already converted. + */ + valueParam = guardedParam; + } + + if (castWhiteList != null && !castWhiteList.contains(guardedParam.getLocalName())) { + continue; + } + + CodeTree cast = createCast(parent, field, valueParam, guardedParam); + if (cast == null) { + continue; + } + builder.tree(cast); + } + + return builder.getRoot(); + } + + private CodeTree createImplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean emitAssumptions) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + // Implict guards based on method signature + String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; + + if (emitAssumptions) { + for (String assumption : guardedSpecialization.getAssumptions()) { + builder.string(andOperator); + builder.string("this"); + builder.string(".").string(assumption).string(".isValid()"); + andOperator = " && "; + } + } + + for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { + NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName()); + if (field == null) { + continue; + } + ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); + + if (valueParam == null) { + /* + * If used inside a function execute method. The value param may not exist. In that + * case it assumes that the value is already converted. + */ + valueParam = guardedParam; + } + + CodeTree implicitGuard = createImplicitGuard(builder, field, valueParam, guardedParam); + if (implicitGuard == null) { + continue; + } + + builder.string(andOperator); + builder.tree(implicitGuard); + andOperator = " && "; + } + + return builder.isEmpty() ? null : builder.getRoot(); + } + + private CodeTree createImplicitGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, ActualParameter target) { + NodeData node = field.getNodeData(); + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + TypeData targetType = target.getTypeSystemType(); + TypeData sourceType = source.getTypeSystemType(); + + if (!sourceType.needsCastTo(getContext(), targetType)) { + return null; + } + + builder.startGroup(); + + if (field.isShortCircuit()) { + ActualParameter shortCircuit = target.getPreviousParameter(); + assert shortCircuit != null; + builder.string("("); + builder.string("!").string(valueName(shortCircuit)); + builder.string(" || "); + } + + startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getTypeSystemType())); + builder.string(valueName(source)); + builder.end().end(); // call + + if (field.isShortCircuit()) { + builder.string(")"); + } + + builder.end(); // group + + return builder.getRoot(); + } + + private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, ActualParameter target) { + NodeData node = field.getNodeData(); + TypeData sourceType = source.getTypeSystemType(); + TypeData targetType = target.getTypeSystemType(); + + if (!sourceType.needsCastTo(getContext(), targetType)) { + return null; + } + + CodeTree condition = null; + if (field.isShortCircuit()) { + ActualParameter shortCircuit = target.getPreviousParameter(); + assert shortCircuit != null; + condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); + } + + CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), CodeTreeBuilder.singleString(valueName(target))); + + return createLazyAssignment(parent, castValueName(target), target.getType(), condition, value); + } + + /** + *

+     * variant1 $condition != null
+     * 
+     * $type $name = defaultValue($type);
+     * if ($condition) {
+     *     $name = $value;
+     * }
+     * 
+     * variant2 $condition != null
+     * $type $name = $value;
+     * 
+ * + * . + */ + private static CodeTree createLazyAssignment(CodeTreeBuilder parent, String name, TypeMirror type, CodeTree condition, CodeTree value) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + if (condition == null) { + builder.declaration(type, name, value); + } else { + builder.declaration(type, name, new CodeTreeBuilder(parent).defaultValue(type).getRoot()); + + builder.startIf().tree(condition).end(); + builder.startBlock(); + builder.startStatement(); + builder.string(name); + builder.string(" = "); + builder.tree(value); + builder.end(); // statement + builder.end(); // block + } + return builder.getRoot(); + } + + protected void emitEncounteredSynthetic(CodeTreeBuilder builder, TemplateMethod current) { + builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)); + builder.startCall("createInfo0"); + builder.doubleQuote("Unsupported values"); + addInternalValueParameterNames(builder, current, current, null, false, true); + builder.end().end().end(); + } + + private static List findUserConstructors(TypeMirror nodeType) { + List constructors = new ArrayList<>(); + for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(nodeType).getEnclosedElements())) { + if (constructor.getModifiers().contains(PRIVATE)) { + continue; + } + if (isCopyConstructor(constructor)) { + continue; + } + constructors.add(constructor); + } + + if (constructors.isEmpty()) { + constructors.add(new CodeExecutableElement(null, Utils.getSimpleName(nodeType))); + } + + return constructors; + } + + private static ExecutableElement findCopyConstructor(TypeMirror type) { + for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(type).getEnclosedElements())) { + if (constructor.getModifiers().contains(PRIVATE)) { + continue; + } + if (isCopyConstructor(constructor)) { + return constructor; + } + } + + return null; + } + + private static boolean isCopyConstructor(ExecutableElement element) { + if (element.getParameters().size() != 1) { + return false; + } + VariableElement var = element.getParameters().get(0); + TypeElement type = Utils.findNearestEnclosingType(var); + + if (!Utils.typeEquals(var.asType(), type.asType())) { + return false; + } + return true; + } + + @Override + protected void createChildren(NodeData node) { + Map> childTypes = new LinkedHashMap<>(); + if (node.getDeclaredNodes() != null && !node.getDeclaredNodes().isEmpty()) { + for (NodeData nodeChild : node.getDeclaredNodes()) { + NodeCodeGenerator generator = new NodeCodeGenerator(getContext()); + childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements()); + } + } + + if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) { + add(new NodeFactoryFactory(context, childTypes), node); + } + } + + private class NodeFactoryFactory extends ClassElementFactory { + + private final Map> childTypes; + + private CodeTypeElement generatedNode; + + public NodeFactoryFactory(ProcessorContext context, Map> childElements) { + super(context); + this.childTypes = childElements; + } + + @Override + protected CodeTypeElement create(NodeData node) { + Modifier visibility = Utils.getVisibility(node.getTemplateType().getModifiers()); + CodeTypeElement clazz = createClass(node, modifiers(), factoryClassName(node), null, false); + if (visibility != null) { + clazz.getModifiers().add(visibility); + } + clazz.getModifiers().add(Modifier.FINAL); + clazz.add(createConstructorUsingFields(modifiers(PRIVATE), clazz)); + return clazz; + } + + @Override + protected void createChildren(NodeData node) { + CodeTypeElement clazz = getElement(); + + Modifier createVisibility = Utils.getVisibility(clazz.getModifiers()); + + if (node.needsFactory()) { + NodeBaseFactory factory = new NodeBaseFactory(context); + add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization()); + generatedNode = factory.getElement(); + + if (node.needsRewrites(context)) { + clazz.add(createCreateGenericMethod(node, createVisibility)); + } + + createFactoryMethods(node, clazz, createVisibility); + + PolymorphicNodeFactory generic = null; + for (SpecializationData specialization : node.getPolymorphicSpecializations()) { + PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(context, generic == null ? generatedNode : generic.getElement(), generic == null); + add(polymorphicFactory, specialization); + if (generic == null) { + generic = polymorphicFactory; + } + } + + for (SpecializationData specialization : node.getSpecializations()) { + if (!specialization.isReachable()) { + continue; + } + add(new SpecializedNodeFactory(context, generatedNode), specialization); + } + + TypeMirror nodeFactory = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType()); + clazz.getImplements().add(nodeFactory); + clazz.add(createCreateNodeMethod(node)); + clazz.add(createCreateNodeGenericMethod(node)); + clazz.add(createGetNodeClassMethod(node)); + clazz.add(createGetNodeSignaturesMethod()); + clazz.add(createGetChildrenSignatureMethod(node)); + clazz.add(createGetInstanceMethod(node, createVisibility)); + clazz.add(createInstanceConstant(node, clazz.asType())); + } + + for (NodeData childNode : childTypes.keySet()) { + if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { + continue; + } + + for (TypeElement type : childTypes.get(childNode)) { + Set typeModifiers = ((CodeTypeElement) type).getModifiers(); + Modifier visibility = Utils.getVisibility(type.getModifiers()); + typeModifiers.clear(); + if (visibility != null) { + typeModifiers.add(visibility); + } + + typeModifiers.add(Modifier.STATIC); + typeModifiers.add(Modifier.FINAL); + clazz.add(type); + } + } + + List children = node.getNodeDeclaringChildren(); + if (node.getParent() == null && children.size() > 0) { + clazz.add(createGetFactories(node)); + } + + } + + private CodeExecutableElement createGetNodeClassMethod(NodeData node) { + TypeMirror returnType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType()); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass"); + CodeTreeBuilder builder = method.createBuilder(); + builder.startReturn().typeLiteral(node.getNodeType()).end(); + return method; + } + + private CodeExecutableElement createGetNodeSignaturesMethod() { + TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class)); + TypeMirror classType = getContext().getType(Class.class); + TypeMirror returnType = Utils.getDeclaredType(listType, Utils.getDeclaredType(listType, classType)); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeSignatures"); + CodeTreeBuilder builder = method.createBuilder(); + builder.startReturn(); + builder.startStaticCall(getContext().getType(Arrays.class), "asList"); + List constructors = findUserConstructors(generatedNode.asType()); + for (ExecutableElement constructor : constructors) { + builder.tree(createAsList(builder, Utils.asTypeMirrors(constructor.getParameters()), classType)); + } + builder.end(); + builder.end(); + return method; + } + + private CodeExecutableElement createGetChildrenSignatureMethod(NodeData node) { + Types types = getContext().getEnvironment().getTypeUtils(); + TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class)); + TypeMirror classType = getContext().getType(Class.class); + TypeMirror nodeType = getContext().getTruffleTypes().getNode(); + TypeMirror wildcardNodeType = types.getWildcardType(nodeType, null); + classType = Utils.getDeclaredType(Utils.fromTypeMirror(classType), wildcardNodeType); + TypeMirror returnType = Utils.getDeclaredType(listType, classType); + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getExecutionSignature"); + CodeTreeBuilder builder = method.createBuilder(); + + 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); + } + + builder.startReturn().tree(createAsList(builder, signatureTypes, classType)).end(); + return method; + } + + private CodeTree createAsList(CodeTreeBuilder parent, List types, TypeMirror elementClass) { + CodeTreeBuilder builder = parent.create(); + builder.startGroup(); + builder.type(getContext().getType(Arrays.class)); + builder.string(".<").type(elementClass).string(">"); + builder.startCall("asList"); + for (TypeMirror typeMirror : types) { + builder.typeLiteral(typeMirror); + } + builder.end().end(); + return builder.getRoot(); + } + + private CodeExecutableElement createCreateNodeMethod(NodeData node) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode"); + CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments"); + method.setVarArgs(true); + method.addParameter(arguments); + + CodeTreeBuilder builder = method.createBuilder(); + List signatures = findUserConstructors(generatedNode.asType()); + boolean ifStarted = false; + + for (ExecutableElement element : signatures) { + ifStarted = builder.startIf(ifStarted); + builder.string("arguments.length == " + element.getParameters().size()); + + int index = 0; + for (VariableElement param : element.getParameters()) { + builder.string(" && "); + if (!param.asType().getKind().isPrimitive()) { + builder.string("(arguments[" + index + "] == null || "); + } + builder.string("arguments[" + index + "] instanceof "); + builder.type(Utils.boxType(getContext(), param.asType())); + if (!param.asType().getKind().isPrimitive()) { + builder.string(")"); + } + index++; + } + builder.end(); + builder.startBlock(); + + builder.startReturn().startCall("create"); + index = 0; + for (VariableElement param : element.getParameters()) { + builder.startGroup(); + builder.string("(").type(param.asType()).string(") "); + builder.string("arguments[").string(String.valueOf(index)).string("]"); + builder.end(); + index++; + } + builder.end().end(); + + builder.end(); // block + } + + builder.startElseBlock(); + builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)); + builder.doubleQuote("Invalid create signature."); + builder.end().end(); + builder.end(); // else block + return method; + } + + private CodeExecutableElement createCreateNodeGenericMethod(NodeData node) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNodeGeneric"); + CodeVariableElement nodeParam = new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME); + method.addParameter(nodeParam); + + CodeTreeBuilder builder = method.createBuilder(); + if (!node.needsRewrites(getContext())) { + builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).doubleQuote("No specialized version.").end().end(); + } else { + builder.startReturn().startCall("createGeneric"); + builder.string(THIS_NODE_LOCAL_VAR_NAME); + builder.end().end(); + } + return method; + } + + private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) { + TypeElement nodeFactoryType = Utils.fromTypeMirror(getContext().getType(NodeFactory.class)); + TypeMirror returnType = Utils.getDeclaredType(nodeFactoryType, node.getNodeType()); + + CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance"); + if (visibility != null) { + method.getModifiers().add(visibility); + } + method.getModifiers().add(Modifier.STATIC); + + String varName = instanceVarName(node); + + CodeTreeBuilder builder = method.createBuilder(); + builder.startIf(); + builder.string(varName).string(" == null"); + builder.end().startBlock(); + + builder.startStatement(); + builder.string(varName); + builder.string(" = "); + builder.startNew(factoryClassName(node)).end(); + builder.end(); + + builder.end(); + builder.startReturn().string(varName).end(); + return method; + } + + private String instanceVarName(NodeData node) { + if (node.getParent() != null) { + return Utils.firstLetterLowerCase(factoryClassName(node)) + "Instance"; + } else { + return "instance"; + } + } + + private CodeVariableElement createInstanceConstant(NodeData node, TypeMirror factoryType) { + String varName = instanceVarName(node); + CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName); + var.getModifiers().add(Modifier.PRIVATE); + var.getModifiers().add(Modifier.STATIC); + return var; + } + + private ExecutableElement createGetFactories(NodeData node) { + List children = node.getNodeDeclaringChildren(); + if (node.needsFactory()) { + children.add(node); + } + + List nodeTypesList = new ArrayList<>(); + TypeMirror prev = null; + boolean allSame = true; + for (NodeData child : children) { + nodeTypesList.add(child.getNodeType()); + if (prev != null && !Utils.typeEquals(child.getNodeType(), prev)) { + allSame = false; + } + prev = child.getNodeType(); + } + TypeMirror commonNodeSuperType = Utils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()])); + + Types types = getContext().getEnvironment().getTypeUtils(); + TypeMirror factoryType = getContext().getType(NodeFactory.class); + TypeMirror baseType; + if (allSame) { + baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType); + } else { + baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null)); + } + TypeMirror listType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType); + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories"); + + CodeTreeBuilder builder = method.createBuilder(); + builder.startReturn(); + builder.startStaticCall(getContext().getType(Arrays.class), "asList"); + + for (NodeData child : children) { + builder.startGroup(); + NodeData childNode = child; + List factories = new ArrayList<>(); + while (childNode.getParent() != null) { + factories.add(childNode); + childNode = childNode.getParent(); + } + Collections.reverse(factories); + for (NodeData nodeData : factories) { + builder.string(factoryClassName(nodeData)).string("."); + } + builder.string("getInstance()"); + builder.end(); + } + builder.end(); + builder.end(); + return method; + } + + private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) { + List constructors = findUserConstructors(generatedNode.asType()); + for (ExecutableElement constructor : constructors) { + clazz.add(createCreateMethod(node, createVisibility, constructor)); + } + } + + private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) { + CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), constructor); + method.setSimpleName(CodeNames.of("create")); + method.getModifiers().clear(); + if (visibility != null) { + method.getModifiers().add(visibility); + } + method.getModifiers().add(Modifier.STATIC); + method.setReturnType(node.getNodeType()); + + CodeTreeBuilder body = method.createBuilder(); + body.startReturn(); + if (node.getSpecializations().isEmpty()) { + body.nullLiteral(); + } else { + body.startNew(nodeSpecializationClassName(node.getSpecializations().get(0))); + for (VariableElement var : method.getParameters()) { + body.string(var.getSimpleName().toString()); + } + body.end(); + } + body.end(); + return method; + } + + private CodeExecutableElement createCreateGenericMethod(NodeData node, Modifier visibility) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(), node.getNodeType(), "createGeneric"); + if (visibility != null) { + method.getModifiers().add(visibility); + } + method.getModifiers().add(Modifier.STATIC); + method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); + + CodeTreeBuilder body = method.createBuilder(); + + SpecializationData found = null; + List specializations = node.getSpecializations(); + for (int i = 0; i < specializations.size(); i++) { + if (specializations.get(i).isReachable()) { + found = specializations.get(i); + } + } + + if (found == null) { + body.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end(); + } else { + body.startReturn().startNew(nodeSpecializationClassName(found)).startGroup().cast(baseClassName(node)).string(THIS_NODE_LOCAL_VAR_NAME).end().end().end(); + } + return method; + } + } + + private class NodeBaseFactory extends ClassElementFactory { + + public NodeBaseFactory(ProcessorContext context) { + super(context); + } + + @Override + protected CodeTypeElement create(SpecializationData specialization) { + NodeData node = specialization.getNode(); + CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false); + + for (NodeChildData child : node.getChildren()) { + clazz.add(createChildField(child)); + + if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) { + ExecutableElement getter = (ExecutableElement) child.getAccessElement(); + CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter); + method.getModifiers().remove(Modifier.ABSTRACT); + method.createBuilder().startReturn().string("this.").string(child.getName()).end(); + clazz.add(method); + } + } + + for (String assumption : node.getAssumptions()) { + clazz.add(createAssumptionField(assumption)); + } + + createConstructors(node, clazz); + + return clazz; + } + + protected String typeGetterName(ActualParameter parameter) { + return "get" + Utils.firstLetterUpperCase(parameter.getLocalName()) + "Type"; + } + + @Override + protected void createChildren(SpecializationData specialization) { + NodeData node = specialization.getNode(); + CodeTypeElement clazz = getElement(); + + if (node.needsRewrites(context)) { + + if (node.getPolymorphicDepth() > 1) { + + CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0"); + var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation())); + clazz.add(var); + + CodeExecutableElement setter = new CodeExecutableElement(modifiers(PROTECTED), context.getType(void.class), "setNext0"); + setter.getParameters().add(new CodeVariableElement(clazz.asType(), "next0")); + CodeTreeBuilder builder = setter.createBuilder(); + builder.statement("this.next0 = adoptChild(next0)"); + clazz.add(setter); + + createTypeGetters(clazz, node.getGenericSpecialization()); + + clazz.add(createCreateSpecialization(node)); + + CodeExecutableElement genericCachedExecute = null; + for (SpecializationData polymorph : node.getPolymorphicSpecializations()) { + CodeExecutableElement cachedExecute = createCachedExecute(node, polymorph, genericCachedExecute); + clazz.add(cachedExecute); + if (genericCachedExecute == null) { + genericCachedExecute = cachedExecute; + } + } + } + + clazz.add(createGenericExecuteAndSpecialize(node)); + clazz.add(createInfoMessage(node)); + } + + if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) { + clazz.add(createGenericExecute(node)); + } + } + + private Element createInfoMessage(NodeData node) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), getContext().getType(String.class), "createInfo0"); + method.addParameter(new CodeVariableElement(getContext().getType(String.class), "message")); + addInternalValueParameters(method, node.getGenericSpecialization(), false, false); + + CodeTreeBuilder builder = method.createBuilder(); + builder.startStatement().string("StringBuilder builder = new StringBuilder(message)").end(); + builder.startStatement().startCall("builder", "append").doubleQuote(" (").end().end(); + + String sep = null; + for (ActualParameter parameter : node.getGenericSpecialization().getParameters()) { + if (!parameter.getSpecification().isSignature()) { + continue; + } + + builder.startStatement(); + builder.string("builder"); + if (sep != null) { + builder.startCall(".append").doubleQuote(sep).end(); + } + builder.startCall(".append").doubleQuote(parameter.getLocalName()).end(); + builder.startCall(".append").doubleQuote(" = ").end(); + builder.startCall(".append").string(parameter.getLocalName()).end(); + builder.end(); + + if (!Utils.isPrimitive(parameter.getType())) { + builder.startIf().string(parameter.getLocalName() + " != null").end(); + builder.startBlock(); + } + builder.startStatement(); + if (Utils.isPrimitive(parameter.getType())) { + builder.startCall("builder.append").doubleQuote(" (" + Utils.getSimpleName(parameter.getType()) + ")").end(); + } else { + builder.startCall("builder.append").doubleQuote(" (").end(); + builder.startCall(".append").string(parameter.getLocalName() + ".getClass().getSimpleName()").end(); + builder.startCall(".append").doubleQuote(")").end(); + } + builder.end(); + if (!Utils.isPrimitive(parameter.getType())) { + builder.end(); + } + + sep = ", "; + } + + builder.startStatement().startCall("builder", "append").doubleQuote(")").end().end(); + + builder.startReturn().string("builder.toString()").end(); + + return method; + } + + protected void createTypeGetters(CodeTypeElement clazz, SpecializationData specialization) { + for (ActualParameter parameter : specialization.getReturnTypeAndParameters()) { + if (!parameter.getSpecification().isSignature()) { + continue; + } + CodeExecutableElement typeGetter = new CodeExecutableElement(modifiers(PROTECTED), context.getType(Class.class), typeGetterName(parameter)); + CodeTreeBuilder builder = typeGetter.createBuilder(); + builder.startReturn().typeLiteral(parameter.getType()).end(); + clazz.add(typeGetter); + } + } + + private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph, CodeExecutableElement genericPolymorphMethod) { + int index = node.getPolymorphicSpecializations().indexOf(polymorph); + assert index != -1; + boolean generic = index == 0; + + String name = "executeCached" + index; + CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED), polymorph.getReturnType().getType(), name); + addInternalValueParameters(cachedExecute, polymorph, true, true); + + if (generic) { + cachedExecute.getModifiers().add(ABSTRACT); + } else { + SpecializationData genericPolymorph = node.getPolymorphicSpecializations().get(0); + CodeTreeBuilder builder = cachedExecute.createBuilder(); + ExecutableTypeData genericExecutable = new ExecutableTypeData(genericPolymorph, genericPolymorphMethod, node.getTypeSystem(), genericPolymorph.getReturnType().getTypeSystemType()); + ExecutableTypeData specificExecutable = new ExecutableTypeData(polymorph, cachedExecute, node.getTypeSystem(), polymorph.getReturnType().getTypeSystemType()); + builder.tree(createCastingExecute(builder, polymorph, specificExecutable, genericExecutable)); + } + + return cachedExecute; + + } + + private CodeExecutableElement createCreateSpecialization(NodeData node) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), getElement().asType(), "createSpezialization0"); + method.getParameters().add(new CodeVariableElement(context.getType(Class.class), "clazz")); + CodeTreeBuilder builder = method.createBuilder(); + + builder.startStatement().type(getElement().asType()).string(" node").end(); + + boolean elseIf = false; + for (SpecializationData specialization : node.getSpecializations()) { + if (specialization.isGeneric() || specialization.isUninitialized()) { + continue; + } + + elseIf = builder.startIf(elseIf); + builder.startGroup().string("clazz == ").string(nodeSpecializationClassName(specialization)).string(".class").end(); + builder.end(); + builder.startBlock(); + builder.startStatement(); + builder.string("node = "); + builder.startNew(nodeSpecializationClassName(specialization)).string("this").end(); + builder.end(); + builder.end(); + } + + builder.startElseBlock(); + builder.startThrow().startNew(context.getType(AssertionError.class)).end().end(); + builder.end(); + + builder.startStatement().startCall("node", "setNext0"); + builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end(); + builder.end().end(); + + builder.startReturn().string("node").end(); + + return method; + } + + private void createConstructors(NodeData node, CodeTypeElement clazz) { + List constructors = findUserConstructors(node.getNodeType()); + if (constructors.isEmpty()) { + clazz.add(createUserConstructor(clazz, null)); + } else { + for (ExecutableElement constructor : constructors) { + clazz.add(createUserConstructor(clazz, constructor)); + } + } + if (node.needsRewrites(getContext())) { + clazz.add(createCopyConstructor(clazz, findCopyConstructor(node.getNodeType()))); + } + } + + private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) { + CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); + CodeTreeBuilder builder = method.createBuilder(); + + NodeData node = getModel().getNode(); + + if (superConstructor != null) { + for (VariableElement param : superConstructor.getParameters()) { + method.getParameters().add(CodeVariableElement.clone(param)); + } + } + + 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()) { + builder.string(param.getSimpleName().toString()); + } + builder.end().end(); + } + + for (VariableElement var : type.getFields()) { + builder.startStatement(); + String fieldName = var.getSimpleName().toString(); + + CodeTree fieldInit = CodeTreeBuilder.singleString(var.getSimpleName().toString()); + builder.string("this.").string(var.getSimpleName().toString()); + + NodeChildData child = node.findChild(fieldName); + if (child != null) { + CreateCastData createCast = node.findCast(child.getName()); + if (createCast != null) { + fieldInit = createTemplateMethodCall(builder, null, node.getGenericSpecialization(), createCast, null, child.getName()); + } + } + + if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) { + builder.string(" = adoptChild(").tree(fieldInit).string(")"); + } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) { + builder.string(" = adoptChildren(").tree(fieldInit).string(")"); + } else { + builder.string(" = ").tree(fieldInit); + } + builder.end(); + } + return method; + } + + private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor) { + CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); + CodeTreeBuilder builder = method.createBuilder(); + if (!(superConstructor == null && type.getFields().isEmpty())) { + method.getParameters().add(new CodeVariableElement(type.asType(), "copy")); + } + + if (superConstructor != null) { + builder.startStatement().startSuperCall().string("copy").end().end(); + } + + for (VariableElement var : type.getFields()) { + builder.startStatement(); + String varName = var.getSimpleName().toString(); + builder.string("this.").string(varName); + if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) { + builder.string(" = adoptChild(copy.").string(varName).string(")"); + } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) { + builder.string(" = adoptChildren(copy.").string(varName).string(")"); + } else { + builder.string(" = copy.").string(varName); + } + builder.end(); + } + if (getModel().getNode().getPolymorphicDepth() > 1) { + builder.statement("this.next0 = adoptChild(copy.next0)"); + } + + return method; + } + + private CodeVariableElement createAssumptionField(String assumption) { + CodeVariableElement var = new CodeVariableElement(getContext().getTruffleTypes().getAssumption(), assumption); + var.getModifiers().add(Modifier.FINAL); + return var; + } + + private CodeVariableElement createChildField(NodeChildData child) { + CodeVariableElement var = new CodeVariableElement(child.getNodeType(), child.getName()); + var.getModifiers().add(Modifier.PROTECTED); + + DeclaredType annotationType; + if (child.getCardinality() == Cardinality.MANY) { + annotationType = getContext().getTruffleTypes().getChildrenAnnotation(); + } else { + annotationType = getContext().getTruffleTypes().getChildAnnotation(); + } + + var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType)); + return var; + } + + private CodeExecutableElement createGenericExecuteAndSpecialize(NodeData node) { + + TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_SPECIALIZE_NAME); + method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); + addInternalValueParameters(method, node.getGenericSpecialization(), true, false); + method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason")); + + CodeTreeBuilder builder = method.createBuilder(); + builder.startStatement(); + builder.startStaticCall(getContext().getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end(); + builder.end(); + + emitSpecializationListeners(builder, node); + builder.defaultDeclaration(node.getGenericSpecialization().getReturnType().getTypeSystemType().getPrimitiveType(), "result"); + + builder.defaultDeclaration(getContext().getType(Class.class), "resultClass"); + + builder.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end(); + + builder.startStatement().string("String message = ").startCall("createInfo0").string("reason"); + addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, false, true); + builder.end().end(); + + String prefix = null; + + List specializations = node.getSpecializations(); + + for (SpecializationData current : specializations) { + if (current.isUninitialized() || !current.isReachable()) { + continue; + } + CodeTreeBuilder execute = new CodeTreeBuilder(builder); + + execute.tree(createGenericInvokeAndSpecialize(builder, node.getGenericSpecialization(), current)); + + if (!current.isGeneric()) { + builder.startStatement().string("allowed = allowed || (minimumState == ").string(nodeSpecializationClassName(current)).string(".class)").end(); + } + + builder.tree(createGuardAndCast(builder, prefix, current.getNode().getGenericSpecialization(), current, true, execute.getRoot(), null, true, false)); + } + + for (SpecializationData current : specializations) { + if (current.isUninitialized() || current.isReachable()) { + continue; + } + builder.string("// unreachable ").string(current.getId()).newLine(); + } + + return method; + } + + private CodeExecutableElement createGenericExecute(NodeData node) { + TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_GENERIC_NAME); + addInternalValueParameters(method, node.getGenericSpecialization(), true, false); + CodeTreeBuilder builder = method.createBuilder(); + + String prefix = null; + List specializations = node.getSpecializations(); + + for (SpecializationData current : specializations) { + if (current.isUninitialized() || !current.isReachable()) { + continue; + } + CodeTreeBuilder execute = new CodeTreeBuilder(builder); + execute.tree(createGenericInvoke(builder, node.getGenericSpecialization(), current)); + builder.tree(createGuardAndCast(builder, prefix, current.getNode().getGenericSpecialization(), current, true, execute.getRoot(), null, true, false)); + } + + for (SpecializationData current : specializations) { + if (current.isUninitialized() || current.isReachable()) { + continue; + } + builder.string("// unreachable ").string(current.getId()).newLine(); + } + + return method; + } + + protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + if (current.getMethod() == null) { + emitEncounteredSynthetic(builder, current); + } else { + builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end(); + } + + return encloseThrowsWithFallThrough(current, builder.getRoot()); + } + + protected CodeTree createGenericInvokeAndSpecialize(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + NodeData node = current.getNode(); + + builder.startIf().string("resultClass == null").end().startBlock(); + if (current.getMethod() != null) { + CodeTree executeCall = createTemplateMethodCall(builder, null, source, current, null); + if (current.getReturnType().getTypeSystemType().isVoid()) { + builder.statement(executeCall); + } else { + builder.startStatement().string("result = ").tree(executeCall).end(); + } + builder.startStatement(); + builder.string("resultClass = ").string(nodeSpecializationClassName(current)).string(".class"); + builder.end(); + } else { + emitEncounteredSynthetic(builder, current); + } + builder.end(); + + boolean ifAllowed = current.hasRewrite(getContext()); + if (ifAllowed) { + builder.startIf().string("allowed").end().startBlock(); + } + + if (!current.isGeneric() || node.getPolymorphicDepth() <= 1) { + // generic rewrite + builder.tree(createRewriteGeneric(builder, current)); + } else { + boolean rewriteableToGeneric = node.getGenericSpecialization().getMethod() != null && node.getGenericSpecialization().isReachable(); + if (rewriteableToGeneric) { + builder.startIf().string("resultClass == ").string(nodeSpecializationClassName(node.getGenericSpecialization())).string(".class").end(); + builder.startBlock(); + + boolean maybePolymorphic = node.getPolymorphicDepth() > 1; + if (maybePolymorphic) { + builder.startIf().string("next0 == null").end(); + builder.startBlock(); + } + builder.tree(createRewriteGeneric(builder, current)); + if (maybePolymorphic) { + builder.end().startElseBlock(); + builder.statement("Node searchNode = super.getParent()"); + builder.startWhile().string("searchNode != null").end(); + builder.startBlock(); + builder.statement("searchNode = searchNode.getParent()"); + builder.startIf().instanceOf("searchNode", nodePolymorphicClassName(node, node.getPolymorphicSpecializations().get(0))).end(); + builder.startBlock().breakStatement().end(); + builder.end(); + builder.startStatement().startCall("searchNode", "replace"); + builder.startGroup().startNew(nodeSpecializationClassName(current)).startGroup().cast(baseClassName(node)).string("searchNode").end().end().end(); + builder.string("message"); + builder.end().end().end(); + } + + builder.end().startElseBlock(); + } + + // polymorphic rewrite + builder.tree(createRewritePolymorphic(builder, node)); + + if (rewriteableToGeneric) { + builder.end(); + } + } + + if (current.getReturnType().getTypeSystemType().isVoid()) { + builder.returnStatement(); + } else { + builder.startReturn().string("result").end(); + } + if (ifAllowed) { + builder.end(); + } + + return encloseThrowsWithFallThrough(current, builder.getRoot()); + } + + private CodeTree encloseThrowsWithFallThrough(SpecializationData current, CodeTree tree) { + if (current.getExceptions().isEmpty()) { + return tree; + } + CodeTreeBuilder builder = new CodeTreeBuilder(null); + + builder.startTryBlock(); + builder.tree(tree); + for (SpecializationThrowsData exception : current.getExceptions()) { + builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx"); + builder.string("// fall through").newLine(); + } + builder.end(); + + return builder.getRoot(); + } + + private CodeTree createRewriteGeneric(CodeTreeBuilder parent, SpecializationData current) { + CodeTreeBuilder builder = parent.create(); + builder.startStatement().startCall("super", "replace"); + builder.startGroup().startNew(nodeSpecializationClassName(current)).string("this").end().end(); + builder.string("message"); + builder.end().end(); + return builder.getRoot(); + } + + private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node) { + CodeTreeBuilder builder = parent.create(); + builder.startStatement(); + builder.string(nodePolymorphicClassName(node, null)); + builder.string(" polymorphic = "); + builder.startNew(nodePolymorphicClassName(node, null)).string("this").end(); + builder.end(); + for (NodeChildData child : node.getChildren()) { + builder.startStatement().string("this.").string(child.getName()).string(" = null").end(); + } + builder.startStatement().startCall("super", "replace"); + builder.string("polymorphic"); + builder.string("message"); + builder.end().end(); + + builder.statement("polymorphic.setNext0(this)"); + builder.statement("setNext0(createSpezialization0(resultClass))"); + + builder.statement("polymorphic.optimizeTypes()"); + 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); + NodeData node = specialization.getNode(); + + ExecutableTypeData castedType = node.findExecutableType(type, 0); + TypeData primaryType = castExecutable.getType(); + + boolean needsTry = castExecutable.hasUnexpectedValue(getContext()); + boolean returnVoid = type.isVoid(); + + List executeParameters = new ArrayList<>(); + for (ActualParameter sourceParameter : executable.getParameters()) { + if (!sourceParameter.getSpecification().isSignature()) { + continue; + } + + ActualParameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName()); + if (targetParameter != null) { + executeParameters.add(targetParameter); + } + } + + builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null, true)); + + CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null); + if (needsTry) { + if (!returnVoid) { + builder.declaration(primaryType.getPrimitiveType(), "value"); + } + builder.startTryBlock(); + + if (returnVoid) { + builder.statement(primaryExecuteCall); + } else { + builder.startStatement(); + builder.string("value = "); + builder.tree(primaryExecuteCall); + builder.end(); + } + + builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); + if (returnVoid) { + builder.string("// ignore").newLine(); + } else { + builder.startReturn(); + builder.tree(createExpectExecutableType(node, specialization.getNode().getTypeSystem().getGenericTypeData(), castedType, CodeTreeBuilder.singleString("ex.getResult()"))); + builder.end(); + } + builder.end(); + + if (!returnVoid) { + builder.startReturn(); + builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, CodeTreeBuilder.singleString("value"))); + builder.end(); + } + } else { + if (returnVoid) { + builder.statement(primaryExecuteCall); + } else { + builder.startReturn(); + builder.tree(createExpectExecutableType(node, castExecutable.getReturnType().getTypeSystemType(), executable, primaryExecuteCall)); + builder.end(); + } + } + + return builder.getRoot(); + } + + protected CodeTree createExpectExecutableType(NodeData node, TypeData sourceType, ExecutableTypeData castedType, CodeTree value) { + boolean hasUnexpected = castedType.hasUnexpectedValue(getContext()); + return createCastType(node, sourceType, castedType.getType(), hasUnexpected, value); + } + + protected CodeTree createCastType(NodeData node, TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) { + if (targetType == null) { + return value; + } else if (!sourceType.needsCastTo(getContext(), targetType)) { + return value; + } + + CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); + String targetMethodName; + if (expect) { + targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(targetType); + } else { + targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(targetType); + } + startCallTypeSystemMethod(getContext(), builder, node, targetMethodName); + + builder.tree(value); + builder.end().end(); + return builder.getRoot(); + } + + protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List targetParameters, + ActualParameter unexpectedParameter, boolean cast) { + NodeData sourceNode = specialization.getNode(); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + for (ActualParameter targetParameter : targetParameters) { + NodeChildData field = sourceNode.findChild(targetParameter.getSpecification().getName()); + if (!targetParameter.getSpecification().isSignature()) { + continue; + } + + TypeData targetType = targetParameter.getTypeSystemType(); + ExecutableTypeData targetExecutable = null; + if (field != null) { + targetExecutable = field.findExecutableType(getContext(), targetType); + } + + ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); + + String targetVariableName = valueName(targetParameter); + CodeTree executionExpression = null; + if ((sourceParameter != null && cast) || sourceParameter != null) { + TypeData sourceType = sourceParameter.getTypeSystemType(); + if (targetExecutable == null || !sourceType.needsCastTo(getContext(), targetType)) { + if (field != null && field.isShortCircuit() && sourceParameter != null) { + builder.tree(createShortCircuitValue(builder, specialization, field, targetParameter.getPreviousParameter(), unexpectedParameter)); + } + builder.startStatement(); + builder.type(targetParameter.getType()).string(" "); + builder.string(valueName(targetParameter)).string(" = "); + builder.tree(CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter))); + builder.end(); + continue; + } else { + CodeTree valueTree = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)); + executionExpression = createExpectExecutableType(sourceNode, sourceType, targetExecutable, valueTree); + } + } else if (sourceParameter == null) { + executionExpression = createExecuteChildExpression(builder, field, targetParameter, unexpectedParameter); + } + + if (executionExpression != null) { + CodeTreeVariable executionVar = new CodeTreeVariable(); + CodeTree shortCircuitTree = createShortCircuitTree(builder, executionVar, targetVariableName, specialization, targetParameter, unexpectedParameter); + CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpression, targetVariableName, specialization, sourceExecutable, targetExecutable, targetParameter, + shortCircuitTree != executionVar); + + executionVar.set(unexpectedTree); + builder.tree(shortCircuitTree); + } + } + return builder.getRoot(); + } + + private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ExecutableTypeData currentExecutable, + ExecutableTypeData targetExecutable, ActualParameter param, boolean shortCircuit) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + boolean unexpected = targetExecutable.hasUnexpectedValue(getContext()); + boolean cast = false; + if (targetExecutable.getType().needsCastTo(getContext(), param.getTypeSystemType())) { + unexpected = true; + cast = true; + } + + if (specialization.isGeneric() && unexpected) { + throw new AssertionError("Generic has unexpected parameters. " + specialization.toString()); + } + + builder.startStatement(); + + if (!shortCircuit) { + builder.type(param.getType()).string(" ").string(targetVariableName); + } + + if (unexpected) { + if (!shortCircuit) { + builder.end(); + } + builder.startTryBlock(); + builder.startStatement(); + builder.string(targetVariableName); + } else if (shortCircuit) { + builder.startStatement(); + builder.string(targetVariableName); + } + builder.string(" = "); + if (cast) { + builder.tree(createCastType(specialization.getNode(), targetExecutable.getType(), param.getTypeSystemType(), true, body)); + } else { + builder.tree(body); + } + builder.end(); + + if (unexpected) { + builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); + SpecializationData generic = specialization.getNode().getGenericSpecialization(); + ActualParameter genericParameter = generic.findParameter(param.getLocalName()); + + List genericParameters = generic.getParametersAfter(genericParameter); + builder.tree(createDeoptimize(builder)); + builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false)); + if (specialization.isPolymorphic()) { + builder.tree(createReturnOptimizeTypes(builder, specialization, param)); + } else { + builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization.findNextSpecialization(), param, "Expected " + param.getLocalName() + " instanceof " + + Utils.getSimpleName(param.getType()))); + } + builder.end(); // catch block + } + + return builder.getRoot(); + } + + private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, SpecializationData specialization, ActualParameter param) { + NodeData node = specialization.getNode(); + assert !node.getPolymorphicSpecializations().isEmpty(); + SpecializationData generic = node.getPolymorphicSpecializations().get(0); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + builder.startReturn(); + + CodeTreeBuilder execute = new CodeTreeBuilder(builder); + execute.startCall("next0", "executeCached0"); + addInternalValueParameterNames(execute, specialization, generic, param.getLocalName(), true, true); + execute.end(); + + TypeData sourceType = generic.getReturnType().getTypeSystemType(); + TypeData targetType = specialization.getReturnType().getTypeSystemType(); + + builder.tree(createCastType(node, sourceType, targetType, true, execute.getRoot())); + + builder.end(); + return builder.getRoot(); + } + + private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetField, ActualParameter sourceParameter, ActualParameter unexpectedParameter) { + TypeData type = sourceParameter.getTypeSystemType(); + ExecutableTypeData execType = targetField.findExecutableType(getContext(), type); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + if (targetField != null) { + Element accessElement = targetField.getAccessElement(); + if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) { + builder.string("this.").string(targetField.getName()); + } else if (accessElement.getKind() == ElementKind.FIELD) { + builder.string("this.").string(accessElement.getSimpleName().toString()); + } else { + throw new AssertionError(); + } + if (sourceParameter.getSpecification().isIndexed()) { + builder.string("[" + sourceParameter.getIndex() + "]"); + } + builder.string("."); + } + + builder.startCall(execType.getMethodName()); + + int index = 0; + for (ActualParameter parameter : execType.getParameters()) { + + if (!parameter.getSpecification().isSignature()) { + builder.string(parameter.getLocalName()); + } else { + if (index < targetField.getExecuteWith().size()) { + NodeChildData child = targetField.getExecuteWith().get(index); + + ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName()); + List specializationParams = getModel().findParameters(spec); + + if (specializationParams.isEmpty()) { + builder.defaultValue(parameter.getType()); + continue; + } + + ActualParameter specializationParam = specializationParams.get(0); + + TypeData targetType = parameter.getTypeSystemType(); + TypeData sourceType = specializationParam.getTypeSystemType(); + String localName = specializationParam.getLocalName(); + + if (unexpectedParameter != null && unexpectedParameter.getLocalName().equals(specializationParam.getLocalName())) { + localName = "ex.getResult()"; + sourceType = getModel().getNode().getTypeSystem().getGenericTypeData(); + } + + CodeTree value = CodeTreeBuilder.singleString(localName); + + if (sourceType.needsCastTo(getContext(), targetType)) { + value = createCallTypeSystemMethod(getContext(), builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value); + } + builder.tree(value); + } else { + builder.defaultValue(parameter.getType()); + } + index++; + } + } + + builder.end(); + + return builder.getRoot(); + } + + private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ActualParameter parameter, + ActualParameter exceptionParam) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName()); + if (forField == null) { + return body; + } + + if (forField.getExecutionKind() != ExecutionKind.SHORT_CIRCUIT) { + return body; + } + + ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter); + + builder.tree(createShortCircuitValue(builder, specialization, forField, shortCircuitParam, exceptionParam)); + + builder.declaration(parameter.getType(), targetVariableName, CodeTreeBuilder.createBuilder().defaultValue(parameter.getType())); + builder.startIf().string(shortCircuitParam.getLocalName()).end(); + builder.startBlock(); + builder.tree(body); + builder.end(); + + return builder.getRoot(); + } + + private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeChildData forField, 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) { + break; + } + shortCircuitIndex++; + } + } + + builder.startStatement().type(shortCircuitParam.getType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); + ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex); + builder.tree(createTemplateMethodCall(builder, null, specialization, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); + builder.end(); // statement + + return builder.getRoot(); + } + + protected CodeTree createDeoptimize(CodeTreeBuilder parent) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + builder.startStatement(); + builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end(); + builder.end(); + return builder.getRoot(); + } + + protected CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData nextSpecialization, ActualParameter exceptionParam, String reason) { + SpecializationData generic = getModel().getNode().getGenericSpecialization(); + CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); + specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); + specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class"); + addInternalValueParameterNames(specializeCall, generic, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true); + specializeCall.doubleQuote(reason); + specializeCall.end().end(); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + builder.startReturn(); + builder.tree(createExpectExecutableType(nextSpecialization.getNode(), generic.getReturnType().getTypeSystemType(), executable, specializeCall.getRoot())); + builder.end(); + + return builder.getRoot(); + } + } + + private class PolymorphicNodeFactory extends SpecializedNodeFactory { + + private final boolean generic; + + public PolymorphicNodeFactory(ProcessorContext context, CodeTypeElement nodeGen, boolean generic) { + super(context, nodeGen); + this.generic = generic; + } + + @Override + public CodeTypeElement create(SpecializationData specialization) { + NodeData node = specialization.getNode(); + TypeMirror baseType = node.getNodeType(); + if (nodeGen != null) { + baseType = nodeGen.asType(); + } + CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC), nodePolymorphicClassName(node, specialization), baseType, false); + + if (!generic) { + clazz.getModifiers().add(Modifier.FINAL); + } + + clazz.getAnnotationMirrors().add(createNodeInfo(node, Kind.POLYMORPHIC)); + + return clazz; + } + + @Override + protected void createChildren(SpecializationData specialization) { +// super.createChildren(specialization); + CodeTypeElement clazz = getElement(); + + createConstructors(clazz); + createExecuteMethods(specialization); + + if (generic) { + getElement().add(createOptimizeTypes()); + createCachedExecuteMethods(specialization); + } + } + + private CodeExecutableElement createOptimizeTypes() { + NodeData node = getModel().getNode(); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), getContext().getType(void.class), "optimizeTypes"); + CodeTreeBuilder builder = method.createBuilder(); + builder.startStatement().string(baseClassName(node)).string(" node = this.next0").end(); + TypeMirror classType = getContext().getType(Class.class); + + SpecializationData genericSpecialization = node.getGenericSpecialization(); + + CodeTreeBuilder whileBodyBuilder = builder.create(); + for (ActualParameter parameter : node.getGenericSpecialization().getReturnTypeAndParameters()) { + if (!parameter.getSpecification().isSignature()) { + continue; + } + + ActualParameter genericParameter = genericSpecialization.findParameter(parameter.getLocalName()); + + String name = parameter.getLocalName() + "Type"; + + builder.declaration(classType, name, builder.create().startCall("node", typeGetterName(parameter)).end().getRoot()); + + whileBodyBuilder.startIf().string(name).string(" != ").startCall("node", typeGetterName(parameter)).end().end(); + whileBodyBuilder.startBlock(); + whileBodyBuilder.startStatement().string(name).string(" = ").typeLiteral(genericParameter.getType()).end(); + whileBodyBuilder.end(); + } + + builder.startWhile().string("node != null && !(").instanceOf("node", nodeSpecializationClassName(node.getUninitializedSpecialization())).string(")").end(); + builder.startBlock(); + builder.tree(whileBodyBuilder.getRoot()); + builder.statement("node = node.next0"); + builder.end(); + + boolean elseIf = false; + for (SpecializationData polymorph : node.getPolymorphicSpecializations()) { + elseIf = builder.startIf(elseIf); + String and = ""; + StringBuilder reason = new StringBuilder("Optimized polymorphic types for ("); + for (ActualParameter parameter : polymorph.getReturnTypeAndParameters()) { + if (!parameter.getSpecification().isSignature()) { + continue; + } + String name = parameter.getLocalName() + "Type"; + builder.string(and).string(name).string(" == ").typeLiteral(parameter.getType()); + + if (!and.isEmpty()) { + reason.append(", "); + } + reason.append(Utils.getSimpleName(parameter.getType())); + and = " && "; + } + reason.append(")"); + builder.end(); + builder.startBlock(); + + String className = nodePolymorphicClassName(node, polymorph); + builder.startIf().string("getClass() != ").string(className).string(".class").end(); + builder.startBlock(); + builder.startStatement().startCall("super", "replace"); + builder.startNew(className).string("this").end(); + builder.doubleQuote(reason.toString()); + builder.end().end(); // call + builder.end(); // block + builder.end(); + } + return method; + } + } + + private class SpecializedNodeFactory extends NodeBaseFactory { + + protected final CodeTypeElement nodeGen; + + public SpecializedNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) { + super(context); + this.nodeGen = nodeGen; + } + + @Override + public CodeTypeElement create(SpecializationData specialization) { + NodeData node = specialization.getNode(); + TypeMirror baseType = node.getNodeType(); + if (nodeGen != null) { + baseType = nodeGen.asType(); + } + CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false); + + Kind kind; + if (specialization.isGeneric()) { + kind = Kind.GENERIC; + } else if (specialization.isUninitialized()) { + kind = Kind.UNINITIALIZED; + } else { + kind = Kind.SPECIALIZED; + } + clazz.getAnnotationMirrors().add(createNodeInfo(node, kind)); + + return clazz; + } + + protected CodeAnnotationMirror createNodeInfo(NodeData node, Kind kind) { + String shortName = node.getShortName(); + CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation()); + if (shortName != null) { + nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName)); + } + + DeclaredType nodeinfoKind = getContext().getTruffleTypes().getNodeInfoKind(); + VariableElement varKind = Utils.findVariableElement(nodeinfoKind, kind.name()); + + nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("kind"), new CodeAnnotationValue(varKind)); + return nodeInfoMirror; + } + + @Override + protected void createChildren(SpecializationData specialization) { + CodeTypeElement clazz = getElement(); + createConstructors(clazz); + + NodeData node = specialization.getNode(); + + if (!specialization.isGeneric() && !specialization.isUninitialized() && !specialization.isPolymorphic() && node.needsRewrites(getContext()) && node.getPolymorphicDepth() > 1) { + + createTypeGetters(clazz, specialization); + } + + createExecuteMethods(specialization); + createCachedExecuteMethods(specialization); + } + + protected void createConstructors(CodeTypeElement clazz) { + TypeElement superTypeElement = Utils.fromTypeMirror(clazz.getSuperclass()); + for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) { + if (getModel().getNode().getUninitializedSpecialization() != null && !getModel().isUninitialized() && + (constructor.getParameters().size() != 1 || constructor.getParameters().get(0).getSimpleName().toString().equals(baseClassName(getModel().getNode())))) { + continue; + } + + CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor); + if (superConstructor != null) { + if (getModel().isGeneric() && getModel().getNode().getPolymorphicDepth() > 1) { + CodeTree body = superConstructor.getBodyTree(); + CodeTreeBuilder builder = superConstructor.createBuilder(); + builder.tree(body); + builder.statement("this.next0 = null"); + } + + clazz.add(superConstructor); + } + } + } + + protected void createExecuteMethods(SpecializationData specialization) { + NodeData node = specialization.getNode(); + CodeTypeElement clazz = getElement(); + + for (ExecutableTypeData execType : node.getExecutableTypes()) { + if (execType.isFinal()) { + continue; + } + CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, true); + clazz.add(executeMethod); + CodeTreeBuilder builder = executeMethod.createBuilder(); + CodeTree result = createExecuteBody(builder, specialization, execType); + if (result != null) { + builder.tree(result); + } else { + clazz.remove(executeMethod); + } + } + } + + protected void createCachedExecuteMethods(SpecializationData specialization) { + NodeData node = specialization.getNode(); + CodeTypeElement clazz = getElement(); + int index = 0; + for (SpecializationData polymorphic : node.getPolymorphicSpecializations()) { + boolean matchFound = false; + if (!specialization.isGeneric() && !specialization.isUninitialized() && !specialization.isPolymorphic()) { + matchFound = polymorphic.getSignature().hasAnyParameterMatch(specialization.getSignature()); + } + + if (matchFound || index == 0) { + ExecutableElement executeCached = nodeGen.getMethod("executeCached" + index); + ExecutableTypeData execType = new ExecutableTypeData(polymorphic, executeCached, node.getTypeSystem(), polymorphic.getReturnType().getTypeSystemType()); + + CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, false); + CodeTreeBuilder builder = executeMethod.createBuilder(); + + if (specialization.isGeneric() || specialization.isPolymorphic()) { + builder.startThrow().startNew(getContext().getType(AssertionError.class)); + builder.doubleQuote("Should not be reached."); + builder.end().end(); + } else if (specialization.isUninitialized()) { + builder.tree(createAppendPolymorphic(builder, specialization)); + } else { + CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); + elseBuilder.startReturn().startCall("this.next0", "executeCached" + index); + addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, true); + elseBuilder.end().end(); + CodeTreeBuilder execute = new CodeTreeBuilder(builder); + execute.tree(createGenericInvoke(builder, polymorphic, specialization)); + boolean forceElse = !specialization.getExceptions().isEmpty(); + builder.tree(createGuardAndCast(builder, null, polymorphic, specialization, true, execute.getRoot(), elseBuilder.getRoot(), true, forceElse)); + } + clazz.add(executeMethod); + } + index++; + } + } + + private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) { + NodeData node = specialization.getNode(); + String genericClassName = nodePolymorphicClassName(node, null); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end(); + + builder.declaration(getContext().getTruffleTypes().getNode(), "searchNode", "super.getParent()"); + builder.declaration(getContext().getType(int.class), "depth", "0"); + builder.startWhile().string("searchNode != null").end(); + builder.startBlock(); + builder.statement("depth++"); + builder.statement("searchNode = searchNode.getParent()"); + + builder.startIf().instanceOf("searchNode", genericClassName).end(); + builder.startBlock().breakStatement().end(); + builder.end(); // if + builder.end(); // while + + builder.startAssert().instanceOf("searchNode", genericClassName).end(); + + builder.startStatement(); + builder.string(genericClassName).string(" ").string("polymorphic = ").string("(").string(genericClassName).string(") searchNode"); + builder.end(); + + builder.startIf().string("depth >= ").string(String.valueOf(node.getPolymorphicDepth())).end(); + builder.startBlock(); + builder.startStatement(); + builder.startCall("searchNode", "replace"); + builder.startNew(nodeSpecializationClassName(node.getGenericSpecialization())).string("this").end(); + builder.doubleQuote("Polymorphic limit reached (" + node.getPolymorphicDepth() + ")"); + builder.end(); + builder.end(); + + builder.startReturn().startCall("super", EXECUTE_GENERIC_NAME); + addInternalValueParameterNames(builder, specialization, node.getGenericSpecialization(), null, true, true); + builder.end().end(); + + builder.end().startElseBlock(); + builder.startStatement().startCall("super", "setNext0"); + builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end(); + builder.end().end(); + + CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder); + specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); + specializeCall.string(nodeSpecializationClassName(node.getUninitializedSpecialization()) + ".class"); + addInternalValueParameterNames(specializeCall, specialization, node.getGenericSpecialization(), null, true, true); + specializeCall.startGroup().doubleQuote("Uninitialized polymorphic (").string(" + depth + ").doubleQuote("/" + node.getPolymorphicDepth() + ")").end(); + specializeCall.end().end(); + + builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot()); + + builder.statement("polymorphic.optimizeTypes()"); + + if (Utils.isVoid(builder.findMethod().getReturnType())) { + builder.returnStatement(); + } else { + builder.startReturn().string("result").end(); + } + + builder.end(); + + return builder.getRoot(); + } + + private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) { + TypeData primaryType = specialization.getReturnType().getTypeSystemType(); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + List primaryExecutes = findFunctionalExecutableType(specialization, execType.getEvaluatedCount()); + + if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) { + builder.tree(createFunctionalExecute(builder, specialization, execType)); + } else if (needsCastingExecuteMethod(execType, primaryType)) { + assert !primaryExecutes.isEmpty(); + builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0))); + } else { + return null; + } + + return builder.getRoot(); + } + + private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) { + CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); + + int i = 0; + for (VariableElement param : method.getParameters()) { + CodeVariableElement var = CodeVariableElement.clone(param); + ActualParameter actualParameter = execType.getParameters().get(i); + if (evaluated && actualParameter.getSpecification().isSignature()) { + var.setName(valueNameEvaluated(actualParameter)); + } else { + var.setName(valueName(actualParameter)); + } + method.getParameters().set(i, var); + i++; + } + + method.getAnnotationMirrors().clear(); + method.getModifiers().remove(Modifier.ABSTRACT); + return method; + } + + private boolean needsCastingExecuteMethod(ExecutableTypeData execType, TypeData primaryType) { + if (execType.isAbstract()) { + return true; + } + if (Utils.isPrimitiveOrVoid(primaryType.getPrimitiveType()) && Utils.isPrimitiveOrVoid(execType.getType().getPrimitiveType())) { + return true; + } + if (execType.getType().isGeneric()) { + return true; + } + return false; + } + + private List findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) { + TypeData primaryType = specialization.getReturnType().getTypeSystemType(); + List otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount); + + List filteredTypes = new ArrayList<>(); + for (ExecutableTypeData compareType : otherTypes) { + if (!Utils.typeEquals(compareType.getType().getPrimitiveType(), primaryType.getPrimitiveType())) { + continue; + } + filteredTypes.add(compareType); + } + + // no direct matches found use generic where the type is Object + if (filteredTypes.isEmpty()) { + for (ExecutableTypeData compareType : otherTypes) { + if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(getContext())) { + filteredTypes.add(compareType); + } + } + } + + if (filteredTypes.isEmpty()) { + for (ExecutableTypeData compareType : otherTypes) { + if (compareType.getType().isGeneric()) { + filteredTypes.add(compareType); + } + } + } + + return filteredTypes; + } + + private CodeTree createFunctionalExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + if (specialization.isUninitialized()) { + builder.tree(createDeoptimize(builder)); + } + + builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null, false)); + + CodeTree executeNode = createExecute(builder, executable, specialization); + + SpecializationData next = specialization.findNextSpecialization(); + CodeTree returnSpecialized = null; + if (next != null) { + CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder); + returnBuilder.tree(createDeoptimize(builder)); + returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, next, null, "One of guards " + specialization.getGuards() + " failed")); + returnSpecialized = returnBuilder.getRoot(); + } + builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized, false, false)); + + return builder.getRoot(); + } + + private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { + NodeData node = specialization.getNode(); + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + if (!specialization.getExceptions().isEmpty() || !specialization.getAssumptions().isEmpty()) { + builder.startTryBlock(); + } + + for (String assumption : specialization.getAssumptions()) { + builder.startStatement(); + builder.string("this.").string(assumption).string(".check()"); + builder.end(); + } + + CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); + if (specialization.isPolymorphic()) { + int index = 0; + if (executable.hasUnexpectedValue(getContext())) { + index = specialization.getNode().getPolymorphicSpecializations().indexOf(specialization); + } + returnBuilder.startCall("next0", "executeCached" + index); + addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true); + returnBuilder.end(); + } else if (specialization.isUninitialized()) { + returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME); + returnBuilder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end(); + addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true); + returnBuilder.doubleQuote("Uninitialized monomorphic"); + returnBuilder.end(); + } else if (specialization.getMethod() == null && !node.needsRewrites(context)) { + emitEncounteredSynthetic(builder, specialization); + } else if (specialization.isGeneric()) { + returnBuilder.startCall("super", EXECUTE_GENERIC_NAME); + addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true); + returnBuilder.end(); + } else { + returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null)); + } + + if (!returnBuilder.isEmpty()) { + builder.startReturn(); + + TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType()); + TypeData sourceType = specialization.getReturnType().getTypeSystemType(); + + if (targetType == null || sourceType == null) { + builder.tree(returnBuilder.getRoot()); + } else if (sourceType.needsCastTo(getContext(), targetType)) { + builder.tree(createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.expectTypeMethodName(targetType), returnBuilder.getRoot())); + } else { + builder.tree(returnBuilder.getRoot()); + } + builder.end(); + } + + if (!specialization.getExceptions().isEmpty()) { + for (SpecializationThrowsData exception : specialization.getExceptions()) { + builder.end().startCatchBlock(exception.getJavaClass(), "ex"); + builder.tree(createDeoptimize(builder)); + builder.tree(createReturnExecuteAndSpecialize(parent, executable, exception.getTransitionTo(), null, "Thrown " + Utils.getSimpleName(exception.getJavaClass()))); + } + builder.end(); + } + if (!specialization.getAssumptions().isEmpty()) { + builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex"); + builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization.findNextSpecialization(), null, "Assumption failed")); + builder.end(); + } + + return builder.getRoot(); + } + + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.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/NodeData.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,552 @@ +/* + * 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 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.NodeChildData.*; +import com.oracle.truffle.dsl.processor.template.*; +import com.oracle.truffle.dsl.processor.typesystem.*; + +public class NodeData extends Template { + + private final String nodeId; + private NodeData declaringNode; + private List declaredNodes = new ArrayList<>(); + private boolean nodeContainer; + + private TypeSystemData typeSystem; + private List children; + private List fields; + private TypeMirror nodeType; + private ParameterSpec instanceParameterSpec; + + private List specializations; + private List polymorphicSpecializations; + private List specializationListeners; + 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) { + super(type, null, null); + this.nodeId = id; + } + + public NodeData(NodeData splitSource, String templateMethodName, String nodeId) { + super(splitSource.getTemplateType(), templateMethodName, null); + this.nodeId = nodeId; + this.declaringNode = splitSource.declaringNode; + this.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 int getPolymorphicDepth() { + return polymorphicDepth; + } + + void setPolymorphicDepth(int polymorphicDepth) { + this.polymorphicDepth = polymorphicDepth; + } + + public List getCasts() { + 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 (typeSystem != null) { + containerChildren.add(typeSystem); + } + if (specializations != null) { + for (MessageContainer specialization : specializations) { + if (specialization.getMessageElement() != null) { + containerChildren.add(specialization); + } + } + } + if (specializationListeners != null) { + containerChildren.addAll(specializationListeners); + } + if (executableTypes != null) { + containerChildren.addAll(getExecutableTypes()); + } + if (shortCircuits != null) { + containerChildren.addAll(shortCircuits); + } + if (children != null) { + containerChildren.addAll(children); + } + if (fields != null) { + containerChildren.addAll(fields); + } + if (casts != null) { + containerChildren.addAll(casts); + } + return containerChildren; + } + + public ParameterSpec getInstanceParameterSpec() { + return instanceParameterSpec; + } + + public void setInstanceParameterSpec(ParameterSpec instanceParameter) { + this.instanceParameterSpec = instanceParameter; + } + + public String getNodeId() { + return nodeId; + } + + public TypeMirror getNodeType() { + if (nodeType != null) { + return nodeType; + } + return getTemplateType().asType(); + } + + void setAssumptions(List assumptions) { + this.assumptions = assumptions; + } + + public List getAssumptions() { + return assumptions; + } + + public boolean needsFactory() { + if (specializations == null) { + return false; + } + if (getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { + return false; + } + + boolean noSpecialization = true; + for (SpecializationData specialization : specializations) { + noSpecialization = noSpecialization && specialization.isGeneric() || specialization.isUninitialized(); + } + return !noSpecialization; + } + + public boolean supportsFrame() { + if (executableTypes != null) { + for (ExecutableTypeData execType : getExecutableTypes(-1)) { + if (execType.findParameter("frameValue") == null) { + return false; + } + } + } + return true; + } + + public List getNodeDeclaringChildren() { + List nodeChildren = new ArrayList<>(); + for (NodeData child : getDeclaredNodes()) { + if (child.needsFactory()) { + nodeChildren.add(child); + } + nodeChildren.addAll(child.getNodeDeclaringChildren()); + } + return nodeChildren; + } + + void setDeclaredNodes(List declaredChildren) { + this.declaredNodes = declaredChildren; + + for (NodeData child : declaredChildren) { + child.declaringNode = this; + } + } + + public NodeData getParent() { + return declaringNode; + } + + public List getDeclaredNodes() { + return declaredNodes; + } + + public void setNodeType(TypeMirror nodeType) { + this.nodeType = nodeType; + } + + public List getAllTemplateMethods() { + List methods = new ArrayList<>(); + + for (SpecializationData specialization : getSpecializations()) { + methods.add(specialization); + } + + methods.addAll(getSpecializationListeners()); + methods.addAll(getExecutableTypes()); + methods.addAll(getShortCircuits()); + if (getCasts() != null) { + methods.addAll(getCasts()); + } + + return methods; + } + + public ExecutableTypeData findGenericExecutableType(ProcessorContext context, TypeData type, int evaluatedCount) { + List types = findGenericExecutableTypes(context, evaluatedCount); + for (ExecutableTypeData availableType : types) { + if (Utils.typeEquals(availableType.getType().getBoxedType(), type.getBoxedType())) { + return availableType; + } + } + return null; + } + + public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context, int evaluatedCount) { + List types = findGenericExecutableTypes(context, evaluatedCount); + for (ExecutableTypeData type : types) { + if (type.getType().isGeneric()) { + return type; + } + } + + for (ExecutableTypeData type : types) { + if (!type.getType().isVoid()) { + return type; + } + } + + for (ExecutableTypeData type : types) { + return type; + } + return null; + } + + public List getExecutableTypes(int evaluatedCount) { + if (executableTypes == null) { + return Collections.emptyList(); + } + if (evaluatedCount == -1) { + List typeData = new ArrayList<>(); + for (int currentEvaluationCount : executableTypes.keySet()) { + typeData.addAll(executableTypes.get(currentEvaluationCount)); + } + return typeData; + } else { + List types = executableTypes.get(evaluatedCount); + if (types == null) { + return Collections.emptyList(); + } + return types; + } + } + + public List findGenericExecutableTypes(ProcessorContext context, int evaluatedCount) { + List types = new ArrayList<>(); + for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) { + if (!type.hasUnexpectedValue(context)) { + types.add(type); + } + } + return types; + } + + public ExecutableTypeData findExecutableType(TypeData prmitiveType, int evaluatedCount) { + for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) { + if (Utils.typeEquals(type.getType().getPrimitiveType(), prmitiveType.getPrimitiveType())) { + return type; + } + } + return null; + } + + public SpecializationData findUniqueSpecialization(TypeData type) { + SpecializationData result = null; + for (SpecializationData specialization : specializations) { + if (specialization.getReturnType().getTypeSystemType() == type) { + if (result != null) { + // Result not unique; + return null; + } + result = specialization; + } + } + 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; + + for (SpecializationData specialization : getSpecializations()) { + if (specialization.hasRewrite(context)) { + needsRewrites = true; + break; + } + } + return needsRewrites || getSpecializations().size() > 1; + } + + public SpecializationData getGenericSpecialization() { + for (SpecializationData specialization : specializations) { + if (specialization.isGeneric()) { + return specialization; + } + } + return null; + } + + public SpecializationData getUninitializedSpecialization() { + for (SpecializationData specialization : specializations) { + if (specialization.isUninitialized()) { + return specialization; + } + } + return null; + } + + @Override + public TypeSystemData getTypeSystem() { + return typeSystem; + } + + public String dump() { + return dump(0); + } + + private String dump(int level) { + String indent = ""; + for (int i = 0; i < level; i++) { + indent += " "; + } + StringBuilder builder = new StringBuilder(); + + builder.append(String.format("%s%s {", indent, toString())); + + dumpProperty(builder, indent, "templateClass", Utils.getQualifiedName(getTemplateType())); + dumpProperty(builder, indent, "typeSystem", getTypeSystem()); + dumpProperty(builder, indent, "fields", getChildren()); + 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) { + builder.append(String.format("\n%s children = [", indent)); + for (NodeData node : getDeclaredNodes()) { + builder.append("\n"); + builder.append(node.dump(level + 1)); + } + builder.append(String.format("\n%s ]", indent)); + } + builder.append(String.format("%s}", indent)); + return builder.toString(); + } + + private static void dumpProperty(StringBuilder b, String indent, String propertyName, Object value) { + if (value instanceof List) { + List list = (List) value; + if (!list.isEmpty()) { + b.append(String.format("\n%s %s = %s", indent, propertyName, dumpList(indent, (List) value))); + } + } else { + if (value != null) { + b.append(String.format("\n%s %s = %s", indent, propertyName, value)); + } + } + } + + private static String dumpList(String indent, List array) { + if (array == null) { + return "null"; + } + + if (array.isEmpty()) { + return "[]"; + } else if (array.size() == 1) { + return "[" + array.get(0).toString() + "]"; + } + + StringBuilder b = new StringBuilder(); + b.append("["); + for (Object object : array) { + b.append("\n "); + b.append(indent); + b.append(object); + b.append(", "); + } + b.append("\n ").append(indent).append("]"); + return b.toString(); + } + + public NodeChildData findChild(String name) { + for (NodeChildData field : getChildren()) { + if (field.getName().equals(name)) { + return field; + } + } + return null; + } + + public List getChildren() { + 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; + } + + public List getExecutableTypes() { + return getExecutableTypes(-1); + } + + public List getShortCircuits() { + 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 setSpecializationListeners(List specializationListeners) { + this.specializationListeners = specializationListeners; + } + + void setExecutableTypes(Map> executableTypes) { + this.executableTypes = executableTypes; + } + + void setShortCircuits(List shortCircuits) { + this.shortCircuits = shortCircuits; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + getNodeId() + "]"; + } + + public CreateCastData findCast(String name) { + if (getCasts() != null) { + for (CreateCastData cast : getCasts()) { + if (cast.getChildNames().contains(name)) { + return cast; + } + } + } + return null; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeFieldData.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/NodeFieldData.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,55 @@ +/* + * 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.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.template.*; + +public class NodeFieldData extends MessageContainer { + + private VariableElement variable; + + public NodeFieldData(VariableElement var) { + this.variable = var; + } + + @Override + public Element getMessageElement() { + return variable; + } + + public String getName() { + return variable.getSimpleName().toString(); + } + + public TypeMirror getType() { + return variable.asType(); + } + + public VariableElement getVariable() { + return variable; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.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/NodeMethodParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -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.dsl.processor.node; + +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.NodeChildData.*; +import com.oracle.truffle.dsl.processor.template.*; + +public abstract class NodeMethodParser extends TemplateMethodParser { + + public NodeMethodParser(ProcessorContext context, NodeData node) { + super(context, node); + } + + public NodeData getNode() { + return template; + } + + @SuppressWarnings("unused") + protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, int evaluatedCount) { + ParameterSpec spec = new ParameterSpec(valueName, nodeTypeMirrors(nodeData)); + spec.setSignature(true); + return spec; + } + + protected List nodeTypeMirrors(NodeData nodeData) { + Set typeMirrors = new LinkedHashSet<>(); + + for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) { + typeMirrors.add(typeData.getType().getPrimitiveType()); + } + + typeMirrors.add(nodeData.getTypeSystem().getGenericType()); + + return new ArrayList<>(typeMirrors); + } + + protected ParameterSpec createReturnParameterSpec() { + return createValueParameterSpec("returnValue", getNode(), 0); + } + + @Override + public boolean isParsable(ExecutableElement method) { + if (getAnnotationType() != null) { + return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; + } + + return true; + } + + @SuppressWarnings("unused") + protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, boolean shortCircuitsEnabled, String shortCircuitName) { + MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec()); + + addDefaultFrame(methodSpec); + addDefaultImplicitThis(method, methodSpec); + addDefaultFieldMethodSpec(method, methodSpec); + addDefaultChildren(shortCircuitsEnabled, shortCircuitName, methodSpec); + + return methodSpec; + } + + private void addDefaultChildren(boolean shortCircuitsEnabled, String shortCircuitName, MethodSpec methodSpec) { + // children are null when parsing executable types + if (getNode().getChildren() != null) { + for (NodeChildData child : getNode().getChildren()) { + if (child.getExecutionKind() == ExecutionKind.DEFAULT) { + ParameterSpec spec = createValueParameterSpec(child.getName(), child.getNodeData(), child.getExecuteWith().size()); + if (child.getCardinality().isMany()) { + spec.setCardinality(Cardinality.MANY); + spec.setIndexed(true); + } + methodSpec.addRequired(spec); + } else if (child.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) { + String valueName = child.getName(); + if (shortCircuitName != null && valueName.equals(shortCircuitName)) { + break; + } + + if (shortCircuitsEnabled) { + methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class))); + } + methodSpec.addRequired(createValueParameterSpec(valueName, child.getNodeData(), child.getExecuteWith().size())); + } else { + assert false; + } + } + } + } + + private void addDefaultFrame(MethodSpec methodSpec) { + if (getNode().supportsFrame()) { + methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame())); + } + } + + protected void addDefaultFieldMethodSpec(ExecutableElement method, MethodSpec methodSpec) { + for (NodeFieldData field : getNode().getFields()) { + if (!Utils.isFieldAccessible(method, field.getVariable())) { + ParameterSpec spec = new ParameterSpec(field.getName(), field.getType()); + spec.setLocal(true); + methodSpec.addOptional(spec); + } + } + } + + protected void addDefaultImplicitThis(ExecutableElement method, MethodSpec methodSpec) { + TypeMirror declaredType = Utils.findNearestEnclosingType(method).asType(); + + if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(getContext(), declaredType, getContext().getTruffleTypes().getNode())) { + methodSpec.addImplicitRequiredType(getNode().getTemplateType().asType()); + } + } + + private static String shortCircuitValueName(String valueName) { + return "has" + Utils.firstLetterUpperCase(valueName); + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.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/NodeParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,1189 @@ +/* + * 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 java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; +import javax.tools.Diagnostic.Kind; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.nodes.*; +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.template.TemplateMethod.*; +import com.oracle.truffle.dsl.processor.typesystem.*; + +public class NodeParser extends TemplateParser { + + 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); + + private Map parsedNodes; + + public NodeParser(ProcessorContext c) { + super(c); + } + + @Override + protected NodeData parse(Element element, AnnotationMirror mirror) { + assert element instanceof TypeElement; + NodeData node = null; + try { + parsedNodes = new HashMap<>(); + node = resolveNode((TypeElement) element); + if (Log.DEBUG) { + NodeData parsed = parsedNodes.get(Utils.getQualifiedName((TypeElement) element)); + if (node != null) { + String dump = parsed.dump(); + log.message(Kind.ERROR, null, null, null, dump); + } + } + } finally { + parsedNodes = null; + } + + return node; + } + + @Override + protected NodeData filterErrorElements(NodeData model) { + for (Iterator iterator = model.getDeclaredNodes().iterator(); iterator.hasNext();) { + NodeData node = filterErrorElements(iterator.next()); + if (node == null) { + iterator.remove(); + } + } + if (model.hasErrors()) { + return null; + } + return model; + } + + @Override + public boolean isDelegateToRootDeclaredType() { + return true; + } + + @Override + public Class getAnnotationType() { + return null; + } + + @Override + public List> getTypeDelegatedAnnotationTypes() { + return ANNOTATIONS; + } + + private NodeData resolveNode(TypeElement rootType) { + String typeName = Utils.getQualifiedName(rootType); + if (parsedNodes.containsKey(typeName)) { + 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); + } + } + + NodeData rootNode = parseNode(rootType); + if (rootNode == null && children.size() > 0) { + rootNode = new NodeData(rootType, rootType.getSimpleName().toString()); + } + + parsedNodes.put(typeName, rootNode); + + if (rootNode != null) { + children.addAll(rootNode.getDeclaredNodes()); + rootNode.setDeclaredNodes(children); + } + + return rootNode; + } + + private NodeData parseNode(TypeElement originalTemplateType) { + // reloading the type elements is needed for ecj + TypeElement templateType = Utils.fromTypeMirror(context.reloadTypeElement(originalTemplateType)); + + if (Utils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) { + // generated nodes should not get called again. + 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) { + 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); + + Set types = new HashSet<>(); + for (ListIterator iterator = lookupTypes.listIterator(); iterator.hasNext();) { + TypeElement typeElement = iterator.next(); + if (types.contains(typeElement)) { + iterator.remove(); + } else { + types.add(typeElement); + } + } + } + List elements = new ArrayList<>(elementSet); + + NodeData node = parseNodeData(templateType, nodeType, elements, lookupTypes); + + if (node.hasErrors()) { + return node; // error sync point + } + + parseMethods(node, elements); + + if (node.hasErrors()) { + return node; + } + + List nodes; + + if (node.isNodeContainer()) { + nodes = splitNodeData(node); + } else { + nodes = new ArrayList<>(); + nodes.add(node); + } + + for (NodeData splittedNode : nodes) { + finalizeSpecializations(elements, splittedNode); + verifyNode(splittedNode, elements); + splittedNode.setPolymorphicSpecializations(createPolymorphicSpecializations(splittedNode)); + assignShortCircuitsToSpecializations(splittedNode); + } + + if (node.isNodeContainer()) { + node.setDeclaredNodes(nodes); + node.setSpecializationListeners(new ArrayList()); + node.setSpecializations(new ArrayList()); + } + return node; + } + + private List createPolymorphicSpecializations(NodeData node) { + if (!node.needsRewrites(context) || node.getPolymorphicDepth() <= 1) { + return Collections.emptyList(); + } + + Signature genericSignature = node.getGenericSpecialization().getSignature(); + Set signatures = new HashSet<>(); + + for (SpecializationData specialization1 : node.getSpecializations()) { + Signature signature = specialization1.getSignature(); + + for (SpecializationData specialization2 : node.getSpecializations()) { + if (specialization1 == specialization2) { + continue; + } + signatures.add(signature.combine(genericSignature, specialization2.getSignature())); + } + } + + while (true) { + List newSignatures = new ArrayList<>(); + for (Signature signature1 : signatures) { + for (Signature signature2 : signatures) { + if (signature1 == signature2) { + continue; + } + newSignatures.add(signature1.combine(genericSignature, signature2)); + } + } + if (!signatures.addAll(newSignatures)) { + break; + } + } + + List sortedSignatures = new ArrayList<>(signatures); + Collections.sort(sortedSignatures); + + List specializations = new ArrayList<>(); + SpecializationData generic = node.getGenericSpecialization(); + for (Signature signature : sortedSignatures) { + SpecializationData specialization = new SpecializationData(generic, false, false, true); + specialization.forceFrame(context.getTruffleTypes().getFrame()); + specialization.setNode(node); + specialization.updateSignature(signature); + + if (specialization.isGenericSpecialization(context)) { + specializations.add(0, specialization); + } else { + specializations.add(specialization); + } + } + + return specializations; + } + + private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List elements, List lookupTypes) { + NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString()); + + AnnotationMirror typeSystemMirror = findFirstAnnotation(lookupTypes, TypeSystemReference.class); + if (typeSystemMirror == null) { + nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(nodeType)); + return nodeData; + } + + TypeMirror typeSytemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value"); + final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true); + if (typeSystem == null) { + nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSytemType)); + return nodeData; + } + + AnnotationMirror polymorphicMirror = findFirstAnnotation(lookupTypes, PolymorphicLimit.class); + if (polymorphicMirror != null) { + AnnotationValue limitValue = Utils.getAnnotationValue(polymorphicMirror, "value"); + int polymorphicLimit = Utils.getAnnotationValue(Integer.class, polymorphicMirror, "value"); + if (polymorphicLimit < 1) { + nodeData.addError(limitValue, "Invalid polymorphic limit %s.", polymorphicLimit); + } + nodeData.setPolymorphicDepth(polymorphicLimit); + } + + List assumptionsList = new ArrayList<>(); + for (int i = lookupTypes.size() - 1; i >= 0; i--) { + TypeElement type = lookupTypes.get(i); + AnnotationMirror assumptions = Utils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class); + if (assumptions != null) { + List assumptionStrings = Utils.getAnnotationValueList(String.class, assumptions, "value"); + for (String string : assumptionStrings) { + if (assumptionsList.contains(string)) { + assumptionsList.remove(string); + } + assumptionsList.add(string); + } + } + } + AnnotationMirror nodeInfoMirror = findFirstAnnotation(lookupTypes, NodeInfo.class); + if (nodeInfoMirror != null) { + nodeData.setShortName(Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName")); + } + + nodeData.setAssumptions(new ArrayList<>(assumptionsList)); + nodeData.setNodeType(nodeType); + AnnotationMirror nodeContainer = findFirstAnnotation(lookupTypes, NodeContainer.class); + nodeData.setNodeContainer(nodeContainer != null); + nodeData.setTypeSystem(typeSystem); + nodeData.setFields(parseFields(elements)); + parsedNodes.put(Utils.getQualifiedName(templateType), nodeData); + // parseChildren invokes cyclic parsing. + nodeData.setChildren(parseChildren(elements, lookupTypes)); + nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements))); + + return nodeData; + } + + private static List parseFields(List elements) { + List fields = new ArrayList<>(); + for (VariableElement field : ElementFilter.fieldsIn(elements)) { + if (field.getModifiers().contains(Modifier.STATIC)) { + continue; + } + if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) { + fields.add(new NodeFieldData(field)); + } + } + return fields; + } + + private List parseChildren(List elements, final List typeHierarchy) { + Set shortCircuits = new HashSet<>(); + for (ExecutableElement method : ElementFilter.methodsIn(elements)) { + AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class); + if (mirror != null) { + shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value")); + } + } + Map castNodeTypes = new HashMap<>(); + for (ExecutableElement method : ElementFilter.methodsIn(elements)) { + AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, CreateCast.class); + if (mirror != null) { + List children = (Utils.getAnnotationValueList(String.class, mirror, "value")); + if (children != null) { + for (String child : children) { + castNodeTypes.put(child, method.getReturnType()); + } + } + } + } + + List parsedChildren = new ArrayList<>(); + 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(); + if (!Utils.isAssignable(context, nodeClassType, context.getTruffleTypes().getNode())) { + 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) { + String name = Utils.getAnnotationValue(String.class, childMirror, "value"); + if (name.equals("")) { + name = "child" + index; + } + + Cardinality cardinality = Cardinality.ONE; + + TypeMirror childType = inheritType(childMirror, "type", nodeClassType); + if (childType.getKind() == TypeKind.ARRAY) { + cardinality = Cardinality.MANY; + } + + TypeMirror originalChildType = childType; + TypeMirror castNodeType = castNodeTypes.get(name); + if (castNodeType != null) { + childType = castNodeType; + } + + Element getter = findGetter(elements, name, childType); + + ExecutionKind kind = ExecutionKind.DEFAULT; + if (shortCircuits.contains(name)) { + kind = ExecutionKind.SHORT_CIRCUIT; + } + + NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality, kind); + + parsedChildren.add(nodeChild); + + verifyNodeChild(nodeChild); + if (nodeChild.hasErrors()) { + continue; + } + + NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(childType)); + nodeChild.setNode(fieldNodeData); + if (fieldNodeData == null) { + nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(childType)); + } + + } + index++; + } + + List filteredChildren = new ArrayList<>(); + Set encounteredNames = new HashSet<>(); + for (int i = parsedChildren.size() - 1; i >= 0; i--) { + NodeChildData child = parsedChildren.get(i); + if (!encounteredNames.contains(child.getName())) { + filteredChildren.add(0, child); + encounteredNames.add(child.getName()); + } + } + + for (NodeChildData child : filteredChildren) { + List executeWithStrings = Utils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith"); + AnnotationValue executeWithValue = Utils.getAnnotationValue(child.getMessageAnnotation(), "executeWith"); + List executeWith = new ArrayList<>(); + for (String executeWithString : executeWithStrings) { + + if (child.getName().equals(executeWithString)) { + child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString); + continue; + } + + NodeChildData found = null; + boolean before = true; + for (NodeChildData resolveChild : filteredChildren) { + if (resolveChild == child) { + before = false; + continue; + } + if (resolveChild.getName().equals(executeWithString)) { + found = resolveChild; + break; + } + } + + if (found == null) { + child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString); + continue; + } else if (!before) { + child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString, + executeWithString); + continue; + } + executeWith.add(found); + } + child.setExecuteWith(executeWith); + if (child.getNodeData() == null) { + continue; + } + + List types = child.findGenericExecutableTypes(context); + if (types.isEmpty()) { + child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", executeWith.size(), Utils.getSimpleName(child.getNodeType())); + continue; + } + } + + 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)); + + List allSpecializations = new ArrayList<>(); + allSpecializations.addAll(generics); + allSpecializations.addAll(specializations); + + node.setSpecializations(allSpecializations); + } + + 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()); + + 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<>(); + } + + 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); + } + + node.setSpecializations(new ArrayList()); + node.setSpecializationListeners(new ArrayList()); + node.setCasts(new ArrayList()); + + return splitted; + } + + private void finalizeSpecializations(List elements, final NodeData node) { + List specializations = new ArrayList<>(node.getSpecializations()); + + if (specializations.isEmpty()) { + return; + } + + for (SpecializationData specialization : specializations) { + matchGuards(elements, specialization); + } + + List generics = new ArrayList<>(); + for (SpecializationData spec : specializations) { + if (spec.isGeneric()) { + generics.add(spec); + } + } + + 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)) { + SpecializationData specialization = specializations.get(0); + GenericParser parser = new GenericParser(context, node); + MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null); + + ExecutableTypeData anyGenericReturnType = node.findAnyGenericExecutableType(context, 0); + assert anyGenericReturnType != null; + + ActualParameter returnType = new ActualParameter(specification.getReturnType(), anyGenericReturnType.getType(), 0, false); + List parameters = new ArrayList<>(); + for (ActualParameter specializationParameter : specialization.getParameters()) { + ParameterSpec parameterSpec = specification.findParameterSpec(specializationParameter.getSpecification().getName()); + NodeChildData child = node.findChild(parameterSpec.getName()); + TypeData actualType; + if (child == null) { + actualType = specializationParameter.getTypeSystemType(); + } else { + ExecutableTypeData paramType = child.findAnyGenericExecutableType(context); + assert paramType != null; + actualType = paramType.getType(); + } + + if (actualType != null) { + parameters.add(new ActualParameter(parameterSpec, actualType, specializationParameter.getIndex(), specializationParameter.isImplicit())); + } else { + parameters.add(new ActualParameter(parameterSpec, specializationParameter.getType(), specializationParameter.getIndex(), specializationParameter.isImplicit())); + } + } + TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters); + genericSpecialization = new SpecializationData(genericMethod, true, false, false); + + specializations.add(genericSpecialization); + } + + 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)); + } + + Collections.sort(specializations); + + node.setSpecializations(specializations); + + List needsId = new ArrayList<>(); + for (SpecializationData specialization : specializations) { + if (specialization.isGeneric()) { + specialization.setId("Generic"); + } else if (specialization.isUninitialized()) { + specialization.setId("Uninitialized"); + } else { + needsId.add(specialization); + } + } + + // 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)); + } + } + + // calculate reachability + int specializationCount = 0; + boolean reachable = true; + for (SpecializationData specialization : specializations) { + if (specialization.isUninitialized()) { + specialization.setReachable(true); + continue; + } + if (!reachable && specialization.getMethod() != null) { + specialization.addError("%s is not reachable.", specialization.isGeneric() ? "Generic" : "Specialization"); + } + specialization.setReachable(reachable); + if (!specialization.hasRewrite(context)) { + reachable = false; + } + if (!specialization.isGeneric()) { + specializationCount++; + } + } + + if (node.getPolymorphicDepth() < 0) { + node.setPolymorphicDepth(specializationCount - 1); + } + + // reduce polymorphicness if generic is not reachable + if (node.getGenericSpecialization() != null && !node.getGenericSpecialization().isReachable()) { + node.setPolymorphicDepth(1); + } + } + + 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) { + int lastSize = -1; + List> signatureChunks = new ArrayList<>(); + for (SpecializationData other : specializations) { + if (other.isUninitialized() || other.isGeneric()) { + 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) { + continue; + } + paramIds.add(Utils.getTypeId(param.getType())); + } + assert lastSize == -1 || lastSize == paramIds.size(); + if (lastSize != -1 && lastSize != paramIds.size()) { + throw new AssertionError(); + } + signatureChunks.add(paramIds); + lastSize = paramIds.size(); + } + + // reduce id vertically + for (int i = 0; i < lastSize; i++) { + String prev = null; + boolean allSame = true; + for (List signature : signatureChunks) { + String arg = signature.get(i); + if (prev == null) { + prev = arg; + continue; + } else if (!prev.equals(arg)) { + allSame = false; + break; + } + prev = arg; + } + + if (allSame) { + for (List signature : signatureChunks) { + signature.remove(i); + } + lastSize--; + } + } + + // reduce id horizontally + for (List signature : signatureChunks) { + if (signature.isEmpty()) { + continue; + } + String prev = null; + boolean allSame = true; + for (String arg : signature) { + if (prev == null) { + prev = arg; + continue; + } else if (!prev.equals(arg)) { + allSame = false; + break; + } + prev = arg; + } + + if (allSame) { + signature.clear(); + signature.add(prev); + } + } + + // create signatures + List signatures = new ArrayList<>(); + for (List signatureChunk : signatureChunks) { + StringBuilder b = new StringBuilder(); + if (signatureChunk.isEmpty()) { + b.append("Default"); + } else { + for (String s : signatureChunk) { + b.append(s); + } + } + signatures.add(b.toString()); + } + + Map counts = new HashMap<>(); + for (String s1 : signatures) { + Integer count = counts.get(s1); + if (count == null) { + count = 0; + } + count++; + counts.put(s1, count); + } + + for (String s : counts.keySet()) { + int count = counts.get(s); + if (count > 1) { + int number = 0; + for (ListIterator iterator = signatures.listIterator(); iterator.hasNext();) { + String s2 = iterator.next(); + if (s.equals(s2)) { + iterator.set(s2 + number); + number++; + } + } + } + } + + return signatures; + } + + private void verifyNode(NodeData nodeData, List elements) { + // verify order is not ambiguous + verifySpecializationOrder(nodeData); + + verifyMissingAbstractMethods(nodeData, elements); + + verifyConstructors(nodeData); + + verifyNamingConvention(nodeData.getShortCircuits(), "needs"); + + verifySpecializationThrows(nodeData); + } + + private static void verifyNodeChild(NodeChildData nodeChild) { + if (nodeChild.getNodeType() == null) { + nodeChild.addError("No valid node type could be resoleved."); + } + // FIXME verify node child + // FIXME verify node type set + } + + private static void verifyMissingAbstractMethods(NodeData nodeData, List originalElements) { + if (!nodeData.needsFactory()) { + // missing abstract methods only needs to be implemented + // if we need go generate factory for it. + return; + } + + List elements = new ArrayList<>(originalElements); + + Set unusedElements = new HashSet<>(elements); + for (TemplateMethod method : nodeData.getAllTemplateMethods()) { + unusedElements.remove(method.getMethod()); + } + if (nodeData.getExtensionElements() != null) { + unusedElements.removeAll(nodeData.getExtensionElements()); + } + + for (NodeChildData child : nodeData.getChildren()) { + if (child.getAccessElement() != null) { + unusedElements.remove(child.getAccessElement()); + } + } + + for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) { + if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) { + nodeData.addError("The type %s must implement the inherited abstract method %s.", Utils.getSimpleName(nodeData.getTemplateType()), Utils.getReadableSignature(unusedMethod)); + } + } + } + + private void verifyConstructors(NodeData nodeData) { + if (!nodeData.needsRewrites(context)) { + // no specialization constructor is needed if the node never rewrites. + return; + } + + TypeElement type = Utils.fromTypeMirror(nodeData.getNodeType()); + List constructors = ElementFilter.constructorsIn(type.getEnclosedElements()); + + boolean parametersFound = false; + for (ExecutableElement constructor : constructors) { + if (!constructor.getParameters().isEmpty()) { + parametersFound = true; + } + } + if (!parametersFound) { + return; + } + for (ExecutableElement e : constructors) { + if (e.getParameters().size() == 1) { + TypeMirror firstArg = e.getParameters().get(0).asType(); + if (Utils.typeEquals(firstArg, nodeData.getNodeType())) { + if (e.getModifiers().contains(Modifier.PRIVATE)) { + nodeData.addError("The specialization constructor must not be private."); + } else if (constructors.size() <= 1) { + nodeData.addError("The specialization constructor must not be the only constructor. The definition of an alternative constructor is required."); + } + return; + } + } + } + + // not found + nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type)); + } + + 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 HashMap<>(); + 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); + if (mirror != null) { + return mirror; + } + } + return null; + } + + private TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) { + TypeMirror inhertNodeType = context.getTruffleTypes().getNode(); + TypeMirror value = Utils.getAnnotationValue(TypeMirror.class, annotation, valueName); + if (Utils.typeEquals(inhertNodeType, value)) { + return parentType; + } else { + return value; + } + } + + private Element findGetter(List elements, String variableName, TypeMirror type) { + if (type == null) { + return null; + } + String methodName; + if (Utils.typeEquals(type, context.getType(boolean.class))) { + methodName = "is" + Utils.firstLetterUpperCase(variableName); + } else { + methodName = "get" + Utils.firstLetterUpperCase(variableName); + } + + for (ExecutableElement method : ElementFilter.methodsIn(elements)) { + if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.isAssignable(context, type, method.getReturnType())) { + return method; + } + } + 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; + } + } + 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 f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitData.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/ShortCircuitData.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,71 @@ +/* + * 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 com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.template.*; + +public class ShortCircuitData extends TemplateMethod { + + private ShortCircuitData genericShortCircuitMethod; + private final String valueName; + + public ShortCircuitData(TemplateMethod template, String valueName) { + super(template); + this.valueName = valueName; + } + + public String getValueName() { + return valueName; + } + + public void setGenericShortCircuitMethod(ShortCircuitData genericShortCircuitMethod) { + this.genericShortCircuitMethod = genericShortCircuitMethod; + } + + public boolean isGeneric() { + return genericShortCircuitMethod == null; + } + + public ShortCircuitData getGeneric() { + if (isGeneric()) { + return this; + } else { + return genericShortCircuitMethod; + } + } + + public boolean isCompatibleTo(SpecializationData specialization) { + if (isGeneric() && specialization.isGeneric()) { + return true; + } + + for (ActualParameter param : getParameters()) { + ActualParameter specializationParam = specialization.findParameter(param.getLocalName()); + if (!Utils.typeEquals(param.getType(), specializationParam.getType())) { + return false; + } + } + return true; + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.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/ShortCircuitParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,76 @@ +/* + * 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 java.util.*; + +import javax.lang.model.element.*; + +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 { + + private final Set shortCircuitValues; + + public ShortCircuitParser(ProcessorContext context, NodeData node) { + super(context, node); + + shortCircuitValues = new HashSet<>(); + NodeChildData[] shortCircuitFields = node.filterFields(ExecutionKind.SHORT_CIRCUIT); + for (NodeChildData field : shortCircuitFields) { + shortCircuitValues.add(field.getName()); + } + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + String shortCircuitValue = Utils.getAnnotationValue(String.class, mirror, "value"); + return createDefaultMethodSpec(method, mirror, true, shortCircuitValue); + } + + @Override + protected ParameterSpec createReturnParameterSpec() { + return new ParameterSpec("has", getContext().getType(boolean.class)); + } + + @Override + public ShortCircuitData create(TemplateMethod method) { + String shortCircuitValue = Utils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value"); + + if (!shortCircuitValues.contains(shortCircuitValue)) { + method.addError("Invalid short circuit value %s.", shortCircuitValue); + } + + return new ShortCircuitData(method, shortCircuitValue); + } + + @Override + public Class getAnnotationType() { + return ShortCircuit.class; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.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/SpecializationData.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,251 @@ +/* + * 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.util.*; + +import javax.lang.model.type.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.template.*; +import com.oracle.truffle.dsl.processor.typesystem.*; + +public class SpecializationData extends TemplateMethod { + + private final int order; + private final boolean generic; + private final boolean polymorphic; + private final boolean uninitialized; + 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) { + super(template); + this.order = order; + this.generic = false; + this.uninitialized = false; + this.polymorphic = false; + this.exceptions = exceptions; + + for (SpecializationThrowsData exception : exceptions) { + exception.setSpecialization(this); + } + } + + 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 void setReachable(boolean reachable) { + this.reachable = reachable; + } + + public boolean isReachable() { + return reachable; + } + + public boolean isPolymorphic() { + return polymorphic; + } + + @Override + protected List findChildContainers() { + List sinks = new ArrayList<>(); + if (exceptions != null) { + sinks.addAll(exceptions); + } + if (guards != null) { + sinks.addAll(guards); + } + return sinks; + } + + public boolean isGenericSpecialization(ProcessorContext context) { + if (isGeneric()) { + return true; + } + if (hasRewrite(context)) { + return false; + } + + for (ActualParameter parameter : getParameters()) { + if (!parameter.getSpecification().isSignature()) { + continue; + } + NodeChildData child = getNode().findChild(parameter.getSpecification().getName()); + if (child == null) { + continue; + } + if (!parameter.getTypeSystemType().isGeneric()) { + return false; + } + } + + return true; + } + + public boolean hasRewrite(ProcessorContext context) { + if (!getExceptions().isEmpty()) { + return true; + } + if (!getGuards().isEmpty()) { + return true; + } + 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()); + if (type.hasUnexpectedValue(context)) { + return true; + } + if (type.getReturnType().getTypeSystemType().needsCastTo(context, parameter.getTypeSystemType())) { + return true; + } + + } + return false; + } + + @Override + public int compareBySignature(TemplateMethod other) { + if (this == other) { + return 0; + } else if (!(other instanceof SpecializationData)) { + return super.compareBySignature(other); + } + + SpecializationData m2 = (SpecializationData) other; + + 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()) { + throw new UnsupportedOperationException("Cannot compare two specializations with different templates."); + } + + return super.compareBySignature(m2); + } + + public NodeData getNode() { + return node; + } + + public void setNode(NodeData node) { + this.node = node; + } + + public void setGuards(List guards) { + this.guards = guards; + } + + public void setGuardDefinitions(List guardDefinitions) { + this.guardDefinitions = guardDefinitions; + } + + public int getOrder() { + return order; + } + + public boolean isGeneric() { + return generic; + } + + public boolean isUninitialized() { + return uninitialized; + } + + public List getExceptions() { + return exceptions; + } + + public List getGuardDefinitions() { + return guardDefinitions; + } + + public List getGuards() { + return guards; + } + + public void setShortCircuits(List shortCircuits) { + this.shortCircuits = shortCircuits; + } + + public List getShortCircuits() { + return shortCircuits; + } + + public List getAssumptions() { + return assumptions; + } + + void setAssumptions(List assumptions) { + this.assumptions = assumptions; + } + + public SpecializationData findNextSpecialization() { + List specializations = node.getSpecializations(); + for (int i = 0; i < specializations.size() - 1; i++) { + if (specializations.get(i) == this) { + return specializations.get(i + 1); + } + } + return null; + } + + public boolean hasDynamicGuards() { + return !getGuards().isEmpty(); + } + + @Override + public String toString() { + return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getSignature()); + } + + public void forceFrame(TypeMirror frameType) { + if (getParameters().isEmpty() || !Utils.typeEquals(getParameters().get(0).getType(), frameType)) { + ParameterSpec frameSpec = getSpecification().findParameterSpec("frame"); + getParameters().add(0, new ActualParameter(frameSpec, frameType, -1, false)); + } + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGuardData.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/SpecializationGuardData.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,83 @@ +/* + * 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 javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.template.*; +import com.oracle.truffle.dsl.processor.typesystem.*; + +public class SpecializationGuardData extends MessageContainer { + + private final SpecializationData specialization; + private final AnnotationValue value; + private final String guardMethod; + private final boolean onSpecialization; + private final boolean onExecution; + + private GuardData guardDeclaration; + + public SpecializationGuardData(SpecializationData specialization, AnnotationValue value, String guardMethod, boolean onSpecialization, boolean onExecution) { + this.specialization = specialization; + this.guardMethod = guardMethod; + this.onSpecialization = onSpecialization; + this.onExecution = onExecution; + this.value = value; + } + + @Override + public Element getMessageElement() { + return specialization.getMessageElement(); + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return specialization.getMessageAnnotation(); + } + + @Override + public AnnotationValue getMessageAnnotationValue() { + return value; + } + + public String getGuardMethod() { + return guardMethod; + } + + public boolean isOnExecution() { + return onExecution; + } + + public boolean isOnSpecialization() { + return onSpecialization; + } + + public void setGuardDeclaration(GuardData compatibleGuard) { + this.guardDeclaration = compatibleGuard; + } + + public GuardData getGuardDeclaration() { + return guardDeclaration; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerData.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/SpecializationListenerData.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.node; + +import com.oracle.truffle.dsl.processor.template.*; + +public class SpecializationListenerData extends TemplateMethod { + + public SpecializationListenerData(TemplateMethod method) { + super(method); + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.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/SpecializationListenerParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,59 @@ +/* + * 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) { + return new SpecializationListenerData(method); + } + + @Override + public Class getAnnotationType() { + return SpecializationListener.class; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.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/SpecializationMethodParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,96 @@ +/* + * 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 java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.template.*; + +public class SpecializationMethodParser extends NodeMethodParser { + + public SpecializationMethodParser(ProcessorContext context, NodeData operation) { + super(context, operation); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + return createDefaultMethodSpec(method, mirror, true, null); + } + + @Override + public SpecializationData create(TemplateMethod method) { + return parseSpecialization(method); + } + + @Override + public Class getAnnotationType() { + return Specialization.class; + } + + private SpecializationData parseSpecialization(TemplateMethod method) { + int order = Utils.getAnnotationValue(Integer.class, method.getMarkerAnnotation(), "order"); + if (order < 0 && order != Specialization.DEFAULT_ORDER) { + method.addError("Invalid order attribute %d. The value must be >= 0 or the default value."); + return null; + } + + AnnotationValue rewriteValue = Utils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn"); + List exceptionTypes = Utils.getAnnotationValueList(TypeMirror.class, method.getMarkerAnnotation(), "rewriteOn"); + List exceptionData = new ArrayList<>(); + for (TypeMirror exceptionType : exceptionTypes) { + SpecializationThrowsData throwsData = new SpecializationThrowsData(method.getMarkerAnnotation(), rewriteValue, exceptionType); + if (!Utils.canThrowType(method.getMethod().getThrownTypes(), exceptionType)) { + throwsData.addError("Method must specify a throws clause with the exception type '%s'.", Utils.getQualifiedName(exceptionType)); + } + exceptionData.add(throwsData); + } + + Collections.sort(exceptionData, new Comparator() { + + @Override + public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) { + return Utils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass()); + } + }); + SpecializationData specialization = new SpecializationData(method, order, exceptionData); + List guardDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); + specialization.setGuardDefinitions(guardDefs); + + List assumptionDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "assumptions"); + specialization.setAssumptions(assumptionDefs); + + for (String assumption : assumptionDefs) { + if (!getNode().getAssumptions().contains(assumption)) { + specialization.addError("Undeclared assumption '%s' used. Use @NodeAssumptions to declare them.", assumption); + } + } + + return specialization; + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationThrowsData.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/SpecializationThrowsData.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,77 @@ +/* + * 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 javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.template.*; + +public class SpecializationThrowsData extends MessageContainer { + + private final AnnotationValue annotationValue; + private final AnnotationMirror annotationMirror; + private final TypeMirror javaClass; + private SpecializationData specialization; + + public SpecializationThrowsData(AnnotationMirror annotationMirror, AnnotationValue value, TypeMirror javaClass) { + this.annotationMirror = annotationMirror; + this.annotationValue = value; + this.javaClass = javaClass; + } + + void setSpecialization(SpecializationData specialization) { + this.specialization = specialization; + } + + @Override + public Element getMessageElement() { + return specialization.getMessageElement(); + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return annotationMirror; + } + + @Override + public AnnotationValue getMessageAnnotationValue() { + return annotationValue; + } + + public TypeMirror getJavaClass() { + return javaClass; + } + + public SpecializationData getSpecialization() { + return specialization; + } + + public AnnotationMirror getAnnotationMirror() { + return annotationMirror; + } + + public SpecializationData getTransitionTo() { + return specialization.findNextSpecialization(); + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,107 @@ +/* + * 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 javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.typesystem.*; + +public class ActualParameter { + + private final ParameterSpec specification; + private TypeData typeSystemType; + private TemplateMethod method; + private final String localName; + private final int index; + private final boolean implicit; + private final TypeMirror type; + + public ActualParameter(ParameterSpec specification, TypeMirror actualType, int index, boolean implicit) { + this.specification = specification; + this.type = actualType; + this.typeSystemType = null; + + this.index = index; + this.implicit = implicit; + String valueName = specification.getName() + "Value"; + + if (specification.isIndexed()) { + valueName += index; + } + this.localName = valueName; + } + + public ActualParameter(ParameterSpec specification, TypeData actualType, int index, boolean implicit) { + this(specification, actualType.getPrimitiveType(), index, implicit); + this.typeSystemType = actualType; + } + + public ActualParameter(ActualParameter parameter, TypeData otherType) { + this(parameter.specification, otherType, parameter.index, parameter.implicit); + } + + public ActualParameter(ActualParameter parameter) { + this.specification = parameter.specification; + this.type = parameter.type; + this.typeSystemType = parameter.typeSystemType; + this.index = parameter.index; + this.implicit = parameter.implicit; + this.localName = parameter.localName; + } + + public boolean isImplicit() { + return implicit; + } + + public int getIndex() { + return index; + } + + public String getLocalName() { + return localName; + } + + void setMethod(TemplateMethod method) { + this.method = method; + } + + public ParameterSpec getSpecification() { + return specification; + } + + public TemplateMethod getMethod() { + return method; + } + + public TypeMirror getType() { + return type; + } + + public TypeData getTypeSystemType() { + return typeSystemType; + } + + public ActualParameter getPreviousParameter() { + return method.getPreviousParam(this); + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ClassElementFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ClassElementFactory.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,140 @@ +/* + * 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 static com.oracle.truffle.dsl.processor.Utils.*; +import static javax.lang.model.element.Modifier.*; + +import java.util.*; + +import javax.lang.model.element.*; +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.ast.*; + +public abstract class ClassElementFactory extends CodeElementFactory { + + public ClassElementFactory(ProcessorContext context) { + super(context); + } + + @Override + protected abstract CodeTypeElement create(M m); + + @Override + public CodeTypeElement getElement() { + return (CodeTypeElement) super.getElement(); + } + + protected CodeExecutableElement createConstructorUsingFields(Set modifiers, CodeTypeElement clazz) { + CodeExecutableElement method = new CodeExecutableElement(modifiers, null, clazz.getSimpleName().toString()); + CodeTreeBuilder builder = method.createBuilder(); + TypeElement superClass = fromTypeMirror(clazz.getSuperclass()); + ExecutableElement constructor = findConstructor(superClass); + if (constructor != null && constructor.getParameters().size() > 0) { + builder.startStatement(); + builder.startSuperCall(); + for (VariableElement parameter : constructor.getParameters()) { + method.addParameter(new CodeVariableElement(parameter.asType(), parameter.getSimpleName().toString())); + builder.string(parameter.getSimpleName().toString()); + } + builder.end(); // super + builder.end(); // statement + } + + for (VariableElement field : clazz.getFields()) { + if (field.getModifiers().contains(STATIC)) { + continue; + } + String fieldName = field.getSimpleName().toString(); + method.addParameter(new CodeVariableElement(field.asType(), fieldName)); + builder.startStatement(); + builder.string("this."); + builder.string(fieldName); + builder.string(" = "); + if (isAssignable(getContext(), field.asType(), getContext().getTruffleTypes().getNode())) { + builder.string("adoptChild(").string(fieldName).string(")"); + } else { + builder.string(fieldName); + } + builder.end(); // statement + } + + return method; + } + + private static ExecutableElement findConstructor(TypeElement clazz) { + List constructors = ElementFilter.constructorsIn(clazz.getEnclosedElements()); + if (constructors.isEmpty()) { + return null; + } else { + return constructors.get(0); + } + } + + protected CodeExecutableElement createSuperConstructor(TypeElement type, ExecutableElement element) { + if (element.getModifiers().contains(Modifier.PRIVATE)) { + return null; + } + CodeExecutableElement executable = CodeExecutableElement.clone(getContext().getEnvironment(), element); + executable.setReturnType(null); + executable.setSimpleName(CodeNames.of(type.getSimpleName().toString())); + CodeTreeBuilder b = executable.createBuilder(); + b.startStatement(); + b.startSuperCall(); + for (VariableElement v : element.getParameters()) { + b.string(v.getSimpleName().toString()); + } + b.end(); + b.end(); + + return executable; + } + + protected CodeTypeElement createClass(Template model, Set modifiers, String simpleName, TypeMirror superType, boolean enumType) { + TypeElement templateType = model.getTemplateType(); + + PackageElement pack = getContext().getEnvironment().getElementUtils().getPackageOf(templateType); + CodeTypeElement clazz = new CodeTypeElement(modifiers, enumType ? ElementKind.ENUM : ElementKind.CLASS, pack, simpleName); + TypeMirror resolvedSuperType = superType; + if (resolvedSuperType == null) { + resolvedSuperType = getContext().getType(Object.class); + } + clazz.setSuperClass(resolvedSuperType); + + CodeAnnotationMirror generatedByAnnotation = new CodeAnnotationMirror((DeclaredType) getContext().getType(GeneratedBy.class)); + generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("value"), new CodeAnnotationValue(templateType.asType())); + if (model.getTemplateMethodName() != null) { + generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("methodName"), new CodeAnnotationValue(model.getTemplateMethodName())); + } + + clazz.addAnnotationMirror(generatedByAnnotation); + + context.registerType(model.getTemplateType(), clazz.asType()); + + return clazz; + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CodeElementFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CodeElementFactory.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,76 @@ +/* + * 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 javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.ast.*; + +public abstract class CodeElementFactory { + + protected final ProcessorContext context; + private M model; + + private CodeElement element; + + public CodeElementFactory(ProcessorContext context) { + this.context = context; + } + + protected abstract CodeElement create(M m); + + @SuppressWarnings("unused") + protected void createChildren(M m) { + } + + @SuppressWarnings("unchecked") + public CodeElement process(CodeElement parent, M m) { + model = m; + element = (CodeElement) create(model); + if (parent != null) { + parent.add(element); + } + if (element != null) { + createChildren(model); + } + return element; + } + + public CodeElement getElement() { + return element; + } + + protected void add(CodeElementFactory factory, MO m) { + factory.process(this.element, m); + } + + public ProcessorContext getContext() { + return context; + } + + public M getModel() { + return model; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CompilationUnitFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/CompilationUnitFactory.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,47 @@ +/* + * 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 com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.ast.*; + +public abstract class CompilationUnitFactory extends CodeElementFactory { + + public CompilationUnitFactory(ProcessorContext context) { + super(context); + } + + @Override + public final CodeCompilationUnit create(M m) { + return new CodeCompilationUnit(); + } + + @Override + public CodeCompilationUnit process(CodeElement parent, M m) { + return (CodeCompilationUnit) super.process(parent, m); + } + + @Override + protected abstract void createChildren(M m); + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/JavaName.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/JavaName.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,50 @@ +/* + * 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 java.util.regex.*; + +public final class JavaName { + + private static final String[] RESERVED_NAMES = new String[]{"abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package", "synchronized", "boolean", "do", "if", + "private", "this", "break", "double", "implements", "protected", "throw", "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", + "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", "finally", "long", "strictfp", "volatile", "const", "float", "native", "super", + "while"}; + + private static final Set RESERVED_NAMES_SET = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(RESERVED_NAMES))); + + private static final Pattern VALID_JAVA_NAME_PATTERN = Pattern.compile("[_a-zA-z][_a-zA-Z0-9]*"); + + private JavaName() { + super(); + } + + public static boolean isReserved(String name) { + return RESERVED_NAMES_SET.contains(name); + } + + public static boolean isValid(String typeName) { + return VALID_JAVA_NAME_PATTERN.matcher(typeName).matches(); + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,191 @@ +/* + * 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.tools.Diagnostic.Kind; + +import com.oracle.truffle.dsl.processor.*; + +public abstract class MessageContainer { + + private final List messages = new ArrayList<>(); + + public final void addWarning(String text, Object... params) { + getMessages().add(new Message(null, this, String.format(text, params), Kind.WARNING)); + } + + public final void addError(String text, Object... params) { + addError(null, text, params); + } + + public final void addError(AnnotationValue value, String text, Object... params) { + getMessages().add(new Message(value, this, String.format(text, params), Kind.ERROR)); + } + + protected List findChildContainers() { + return Collections.emptyList(); + } + + public abstract Element getMessageElement(); + + public final void emitMessages(TypeElement baseElement, Log log) { + emitMessagesImpl(baseElement, log, new HashSet()); + } + + private void emitMessagesImpl(TypeElement baseElement, Log log, Set visitedSinks) { + for (Message message : getMessages()) { + emitDefault(baseElement, log, message); + } + + for (MessageContainer sink : findChildContainers()) { + if (visitedSinks.contains(sink)) { + continue; + } + + visitedSinks.add(sink); + sink.emitMessagesImpl(baseElement, log, visitedSinks); + } + } + + private void emitDefault(TypeElement baseType, Log log, Message message) { + TypeElement rootEnclosing = Utils.findRootEnclosingType(getMessageElement()); + if (rootEnclosing != null && Utils.typeEquals(baseType.asType(), rootEnclosing.asType()) && this == message.getOriginalContainer()) { + log.message(message.getKind(), getMessageElement(), getMessageAnnotation(), getMessageAnnotationValue(), message.getText()); + } else { + MessageContainer original = message.getOriginalContainer(); + log.message(message.getKind(), baseType, null, null, wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText())); + } + } + + private static String wrapText(Element element, AnnotationMirror mirror, String text) { + StringBuilder b = new StringBuilder(); + if (element != null) { + b.append("Element " + element.toString()); + } + if (mirror != null) { + b.append(" at annotation @" + Utils.getSimpleName(mirror.getAnnotationType())); + } + + if (b.length() > 0) { + b.append(" is erroneous: ").append(text); + return b.toString(); + } else { + return text; + } + } + + public AnnotationMirror getMessageAnnotation() { + return null; + } + + public AnnotationValue getMessageAnnotationValue() { + return null; + } + + public final boolean hasErrors() { + return hasErrorsImpl(new HashSet()); + } + + public final List collectMessages() { + List collectedMessages = new ArrayList<>(); + collectMessagesImpl(collectedMessages, new HashSet()); + return collectedMessages; + } + + private void collectMessagesImpl(List collectedMessages, Set visitedSinks) { + collectedMessages.addAll(getMessages()); + for (MessageContainer sink : findChildContainers()) { + if (visitedSinks.contains(sink)) { + return; + } + + visitedSinks.add(sink); + sink.collectMessagesImpl(collectedMessages, visitedSinks); + } + } + + private boolean hasErrorsImpl(Set visitedSinks) { + for (Message msg : getMessages()) { + if (msg.getKind() == Kind.ERROR) { + return true; + } + } + for (MessageContainer sink : findChildContainers()) { + if (visitedSinks.contains(sink)) { + return false; + } + + visitedSinks.add(sink); + + if (sink.hasErrorsImpl(visitedSinks)) { + return true; + } + } + return false; + } + + public List getMessages() { + return messages; + } + + public static final class Message { + + private final MessageContainer originalContainer; + private final AnnotationValue annotationValue; + private final String text; + private final Kind kind; + + public Message(AnnotationValue annotationValue, MessageContainer originalContainer, String text, Kind kind) { + this.annotationValue = annotationValue; + this.originalContainer = originalContainer; + this.text = text; + this.kind = kind; + } + + public AnnotationValue getAnnotationValue() { + return annotationValue; + } + + public MessageContainer getOriginalContainer() { + return originalContainer; + } + + public String getText() { + return text; + } + + public Kind getKind() { + return kind; + } + + @Override + public String toString() { + return kind + ": " + text; + } + + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,228 @@ +/* + * 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.type.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.node.NodeChildData.*; + +public class MethodSpec { + + private final List implicitRequiredTypes = new ArrayList<>(); + + private final ParameterSpec returnType; + private final List optional = new ArrayList<>(); + private final List required = new ArrayList<>(); + + private boolean variableRequiredArguments; + private List typeDefinitions; + + public MethodSpec(ParameterSpec returnType) { + this.returnType = returnType; + } + + public void setVariableRequiredArguments(boolean variableArguments) { + this.variableRequiredArguments = variableArguments; + } + + public boolean isVariableRequiredArguments() { + return variableRequiredArguments; + } + + public void addImplicitRequiredType(TypeMirror type) { + this.implicitRequiredTypes.add(type); + } + + public void addOptional(ParameterSpec spec) { + optional.add(spec); + } + + public ParameterSpec addRequired(ParameterSpec spec) { + required.add(spec); + return spec; + } + + public List getImplicitRequiredTypes() { + return implicitRequiredTypes; + } + + public ParameterSpec getReturnType() { + return returnType; + } + + public List getRequired() { + return required; + } + + public List getOptional() { + return optional; + } + + public List getAll() { + List specs = new ArrayList<>(); + specs.add(getReturnType()); + specs.addAll(getOptional()); + specs.addAll(getRequired()); + return specs; + } + + public ParameterSpec findParameterSpec(String name) { + for (ParameterSpec spec : getAll()) { + if (spec.getName().equals(name)) { + return spec; + } + } + return null; + } + + public void applyTypeDefinitions(String prefix) { + this.typeDefinitions = createTypeDefinitions(prefix); + } + + private List createTypeDefinitions(String prefix) { + List typeDefs = new ArrayList<>(); + + int defIndex = 0; + for (ParameterSpec spec : getAll()) { + List allowedTypes = spec.getAllowedTypes(); + List types = spec.getAllowedTypes(); + if (types != null && allowedTypes.size() > 1) { + TypeDef foundDef = null; + for (TypeDef def : typeDefs) { + if (allowedTypes.equals(def.getTypes())) { + foundDef = def; + break; + } + } + if (foundDef == null) { + foundDef = new TypeDef(types, prefix + defIndex); + typeDefs.add(foundDef); + defIndex++; + } + + spec.setTypeDefinition(foundDef); + } + } + + return typeDefs; + } + + public String toSignatureString(String methodName) { + StringBuilder b = new StringBuilder(); + b.append(" "); + b.append(createTypeSignature(returnType, true)); + + b.append(" "); + b.append(methodName); + b.append("("); + + String sep = ""; + + for (ParameterSpec optionalSpec : getOptional()) { + b.append(sep); + b.append("["); + b.append(createTypeSignature(optionalSpec, false)); + b.append("]"); + sep = ", "; + } + + for (ParameterSpec requiredSpec : getRequired()) { + b.append(sep); + if (requiredSpec.getCardinality() == Cardinality.MANY) { + b.append("{"); + } + b.append(createTypeSignature(requiredSpec, false)); + if (requiredSpec.getCardinality() == Cardinality.MANY) { + b.append("}"); + } + sep = ", "; + } + + b.append(")"); + + if (typeDefinitions != null && !typeDefinitions.isEmpty()) { + b.append("\n\n"); + + String lineSep = ""; + for (TypeDef def : typeDefinitions) { + b.append(lineSep); + b.append(" <").append(def.getName()).append(">"); + b.append(" = {"); + String separator = ""; + for (TypeMirror type : def.getTypes()) { + b.append(separator).append(Utils.getSimpleName(type)); + separator = ", "; + } + b.append("}"); + lineSep = "\n"; + + } + } + return b.toString(); + } + + private static String createTypeSignature(ParameterSpec spec, boolean typeOnly) { + StringBuilder builder = new StringBuilder(); + TypeDef foundTypeDef = spec.getTypeDefinition(); + if (foundTypeDef != null) { + builder.append("<" + foundTypeDef.getName() + ">"); + } else if (spec.getAllowedTypes().size() >= 1) { + builder.append(Utils.getSimpleName(spec.getAllowedTypes().get(0))); + } else { + builder.append("void"); + } + if (!typeOnly) { + builder.append(" "); + builder.append(spec.getName()); + } + return builder.toString(); + } + + @Override + public String toString() { + return toSignatureString("methodName"); + } + + static class TypeDef { + + private final List types; + private final String name; + + public TypeDef(List types, String name) { + this.types = types; + this.name = name; + } + + public List getTypes() { + return types; + } + + public String getName() { + return name; + } + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,146 @@ +/* + * 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.type.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.node.NodeChildData.*; +import com.oracle.truffle.dsl.processor.template.MethodSpec.*; + +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; + + 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(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.allowedTypes = allowedTypes; + } + + void setTypeDefinition(TypeDef typeDefinition) { + this.typeDefinition = typeDefinition; + } + + TypeDef getTypeDefinition() { + return typeDefinition; + } + + public void setSignature(boolean signature) { + this.signature = signature; + } + + public void setLocal(boolean local) { + this.local = local; + } + + public boolean isSignature() { + return signature; + } + + 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; + } + + public boolean matches(TypeMirror actualType) { + for (TypeMirror mirror : allowedTypes) { + if (Utils.typeEquals(actualType, mirror)) { + return true; + } + } + return false; + } + + @Override + public String toString() { + return toSignatureString(false); + } + + public String toSignatureString(boolean typeOnly) { + StringBuilder builder = new StringBuilder(); + if (typeDefinition != null) { + builder.append("<" + typeDefinition.getName() + ">"); + } else if (getAllowedTypes().size() >= 1) { + builder.append(Utils.getSimpleName(getAllowedTypes().get(0))); + } else { + builder.append("void"); + } + if (!typeOnly) { + builder.append(" "); + builder.append(getName()); + } + return builder.toString(); + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/Template.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/Template.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,84 @@ +/* + * 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 com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.api.element.*; +import com.oracle.truffle.dsl.processor.typesystem.*; + +public abstract class Template extends MessageContainer { + + private final TypeElement templateType; + private final String templateMethodName; + private final AnnotationMirror annotation; + + private List extensionElements; + + public Template(TypeElement templateType, String templateMethodName, AnnotationMirror annotation) { + this.templateType = templateType; + this.templateMethodName = templateMethodName; + this.annotation = annotation; + } + + public abstract TypeSystemData getTypeSystem(); + + @Override + public Element getMessageElement() { + return templateType; + } + + @Override + protected List findChildContainers() { + return Collections.emptyList(); + } + + public String getTemplateMethodName() { + return templateMethodName; + } + + public TypeElement getTemplateType() { + return templateType; + } + + public AnnotationMirror getTemplateTypeAnnotation() { + return annotation; + } + + public List getExtensionElements() { + return extensionElements; + } + + public void setExtensionElements(List extensionMethods) { + this.extensionElements = extensionMethods; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + Utils.getSimpleName(getTemplateType()) + "]"; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,393 @@ +/* + * 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.type.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.typesystem.*; + +/** + * Note: this class has a natural ordering that is inconsistent with equals. + */ +public class TemplateMethod extends MessageContainer implements Comparable { + + private String id; + private final Template template; + private final MethodSpec specification; + private final ExecutableElement method; + private final AnnotationMirror markerAnnotation; + private ActualParameter returnType; + private List parameters; + + public TemplateMethod(String id, Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType, + List parameters) { + this.template = template; + this.specification = specification; + this.method = method; + this.markerAnnotation = markerAnnotation; + this.returnType = returnType; + this.parameters = new ArrayList<>(); + for (ActualParameter param : parameters) { + ActualParameter newParam = new ActualParameter(param); + this.parameters.add(newParam); + newParam.setMethod(this); + } + this.id = id; + } + + public TemplateMethod(TemplateMethod method) { + this(method.id, method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters); + getMessages().addAll(method.getMessages()); + } + + public TemplateMethod(TemplateMethod method, ExecutableElement executable) { + this(method.id, method.template, method.specification, executable, method.markerAnnotation, method.returnType, method.parameters); + getMessages().addAll(method.getMessages()); + } + + public void setParameters(List parameters) { + this.parameters = parameters; + } + + @Override + public Element getMessageElement() { + return method; + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return markerAnnotation; + } + + @Override + protected List findChildContainers() { + return Collections.emptyList(); + } + + public void setId(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public Template getTemplate() { + return template; + } + + public MethodSpec getSpecification() { + return specification; + } + + public ActualParameter getReturnType() { + return returnType; + } + + public void replaceParameter(String localName, ActualParameter newParameter) { + if (returnType.getLocalName().equals(localName)) { + returnType = newParameter; + returnType.setMethod(this); + } + + for (ListIterator iterator = parameters.listIterator(); iterator.hasNext();) { + ActualParameter parameter = iterator.next(); + if (parameter.getLocalName().equals(localName)) { + iterator.set(newParameter); + newParameter.setMethod(this); + } + } + } + + public List getRequiredParameters() { + List requiredParameters = new ArrayList<>(); + for (ActualParameter parameter : getParameters()) { + if (getSpecification().getRequired().contains(parameter.getSpecification())) { + requiredParameters.add(parameter); + } + } + return requiredParameters; + } + + public List getParameters() { + return parameters; + } + + public List findParameters(ParameterSpec spec) { + List foundParameters = new ArrayList<>(); + for (ActualParameter param : getReturnTypeAndParameters()) { + if (param.getSpecification().equals(spec)) { + foundParameters.add(param); + } + } + return foundParameters; + } + + public ActualParameter findParameter(String valueName) { + for (ActualParameter param : getReturnTypeAndParameters()) { + if (param.getLocalName().equals(valueName)) { + return param; + } + } + return null; + } + + public List getReturnTypeAndParameters() { + List allParameters = new ArrayList<>(getParameters().size() + 1); + if (getReturnType() != null) { + allParameters.add(getReturnType()); + } + allParameters.addAll(getParameters()); + return Collections.unmodifiableList(allParameters); + } + + public boolean canBeAccessedByInstanceOf(ProcessorContext context, TypeMirror type) { + TypeMirror methodType = Utils.findNearestEnclosingType(getMethod()).asType(); + return Utils.isAssignable(context, type, methodType) || Utils.isAssignable(context, methodType, type); + } + + public ExecutableElement getMethod() { + return method; + } + + public String getMethodName() { + if (getMethod() != null) { + return getMethod().getSimpleName().toString(); + } else { + return "$synthetic"; + } + } + + public AnnotationMirror getMarkerAnnotation() { + return markerAnnotation; + } + + @Override + public String toString() { + return String.format("%s [id = %s, method = %s]", getClass().getSimpleName(), getId(), getMethod()); + } + + public ActualParameter getPreviousParam(ActualParameter searchParam) { + ActualParameter prev = null; + for (ActualParameter param : getParameters()) { + if (param == searchParam) { + return prev; + } + prev = param; + } + return prev; + } + + public Signature getSignature() { + Signature signature = new Signature(); + for (ActualParameter parameter : getReturnTypeAndParameters()) { + if (!parameter.getSpecification().isSignature()) { + continue; + } + TypeData typeData = parameter.getTypeSystemType(); + if (typeData != null) { + signature.types.add(typeData); + } + } + return signature; + } + + public void updateSignature(Signature signature) { + assert signature.size() >= 1; + int signatureIndex = 0; + for (ActualParameter parameter : getReturnTypeAndParameters()) { + if (!parameter.getSpecification().isSignature()) { + continue; + } + TypeData newType = signature.get(signatureIndex++); + if (!parameter.getTypeSystemType().equals(newType)) { + replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, newType)); + } + } + } + + @Override + public int compareTo(TemplateMethod o) { + if (this == o) { + return 0; + } + + int compare = compareBySignature(o); + if (compare == 0) { + // if signature sorting failed sort by id + compare = getId().compareTo(o.getId()); + } + if (compare == 0) { + // if still no difference sort by enclosing type name + TypeElement enclosingType1 = Utils.findNearestEnclosingType(getMethod()); + TypeElement enclosingType2 = Utils.findNearestEnclosingType(o.getMethod()); + compare = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString()); + } + return compare; + } + + public List getParametersAfter(ActualParameter genericParameter) { + boolean found = false; + List foundParameters = new ArrayList<>(); + for (ActualParameter param : getParameters()) { + if (param.getLocalName().equals(genericParameter.getLocalName())) { + found = true; + } else if (found) { + foundParameters.add(param); + } + } + return foundParameters; + } + + public int compareBySignature(TemplateMethod compareMethod) { + TypeSystemData typeSystem = getTemplate().getTypeSystem(); + if (typeSystem != compareMethod.getTemplate().getTypeSystem()) { + throw new IllegalStateException("Cannot compare two methods with different type systems."); + } + + Signature signature1 = getSignature(); + Signature signature2 = compareMethod.getSignature(); + if (signature1.size() != signature2.size()) { + return signature2.size() - signature1.size(); + } + + int result = 0; + for (int i = 1; i < signature1.size(); i++) { + int typeResult = compareActualParameter(typeSystem, signature1.get(i), signature2.get(i)); + if (result == 0) { + result = typeResult; + } else if (typeResult != 0 && Math.signum(result) != Math.signum(typeResult)) { + // We cannot define an order. + return 0; + } + } + if (result == 0 && signature1.size() > 0) { + result = compareActualParameter(typeSystem, signature1.get(0), signature2.get(0)); + } + + return result; + } + + private static int compareActualParameter(TypeSystemData typeSystem, TypeData t1, TypeData t2) { + int index1 = typeSystem.findType(t1); + int index2 = typeSystem.findType(t2); + return index1 - index2; + } + + public static class Signature implements Iterable, Comparable { + + final List types; + + public Signature() { + this.types = new ArrayList<>(); + } + + public Signature(List signature) { + this.types = signature; + } + + @Override + public int hashCode() { + return types.hashCode(); + } + + public int compareTo(Signature o) { + if (o.size() != size()) { + return size() - o.size(); + } + + int typeSum = 0; + int otherTypeSum = 0; + for (int i = 0; i < types.size(); i++) { + TypeData type = types.get(i); + TypeData otherType = o.get(i); + typeSum += type.isGeneric() ? 1 : 0; + otherTypeSum += otherType.isGeneric() ? 1 : 0; + } + + return typeSum - otherTypeSum; + } + + public int size() { + return types.size(); + } + + public TypeData get(int index) { + return types.get(index); + } + + public Signature combine(Signature genericSignature, Signature other) { + assert types.size() == other.types.size(); + assert genericSignature.types.size() == other.types.size(); + + if (this.equals(other)) { + return this; + } + + Signature signature = new Signature(); + for (int i = 0; i < types.size(); i++) { + TypeData type1 = types.get(i); + TypeData type2 = other.types.get(i); + if (type1.equals(type2)) { + signature.types.add(type1); + } else { + signature.types.add(genericSignature.types.get(i)); + } + } + return signature; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Signature) { + return ((Signature) obj).types.equals(types); + } + return super.equals(obj); + } + + public Iterator iterator() { + return types.iterator(); + } + + @Override + public String toString() { + return types.toString(); + } + + public boolean hasAnyParameterMatch(Signature other) { + for (int i = 1; i < types.size(); i++) { + TypeData type1 = types.get(i); + TypeData type2 = other.types.get(i); + if (type1.equals(type2)) { + return true; + } + } + return false; + } + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,338 @@ +/* + * 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 static com.oracle.truffle.dsl.processor.Utils.*; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +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 { + + private final ProcessorContext context; + + protected final T template; + + private boolean emitErrors = true; + private boolean parseNullOnError = true; + + public TemplateMethodParser(ProcessorContext context, T template) { + this.template = template; + this.context = context; + } + + public boolean isEmitErrors() { + return emitErrors; + } + + public void setParseNullOnError(boolean nullOnError) { + this.parseNullOnError = nullOnError; + } + + public boolean isParseNullOnError() { + return parseNullOnError; + } + + public void setEmitErrors(boolean emitErrors) { + this.emitErrors = emitErrors; + } + + public ProcessorContext getContext() { + return context; + } + + public TypeSystemData getTypeSystem() { + return template.getTypeSystem(); + } + + public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror); + + public abstract E create(TemplateMethod method); + + public abstract boolean isParsable(ExecutableElement method); + + public Class getAnnotationType() { + return null; + } + + public final List parse(List elements) { + List methods = new ArrayList<>(); + methods.addAll(ElementFilter.methodsIn(elements)); + + List parsedMethods = new ArrayList<>(); + boolean valid = true; + for (ExecutableElement method : methods) { + if (!isParsable(method)) { + continue; + } + + Class annotationType = getAnnotationType(); + AnnotationMirror mirror = null; + if (annotationType != null) { + mirror = Utils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType); + } + + E parsedMethod = parse(method, mirror); + + if (method.getModifiers().contains(Modifier.PRIVATE) && emitErrors) { + parsedMethod.addError("Method must not be private."); + valid = false; + continue; + } + + if (parsedMethod != null) { + parsedMethods.add(parsedMethod); + } else { + valid = false; + } + } + Collections.sort(parsedMethods); + + if (!valid && parseNullOnError) { + return null; + } + return parsedMethods; + } + + private E parse(ExecutableElement method, AnnotationMirror annotation) { + MethodSpec methodSpecification = createSpecification(method, annotation); + if (methodSpecification == null) { + return null; + } + + 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"); + } + + ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); + + ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, false); + if (returnTypeMirror == null) { + if (emitErrors) { + E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList())); + String expectedReturnType = returnTypeSpec.toSignatureString(true); + String actualReturnType = Utils.getSimpleName(method.getReturnType()); + + String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType, + methodSpecification.toSignatureString(method.getSimpleName().toString())); + invalidMethod.addError(message); + return invalidMethod; + } else { + return null; + } + } + + List parameterTypes = new ArrayList<>(); + for (VariableElement var : method.getParameters()) { + parameterTypes.add(var.asType()); + } + + List parameters = parseParameters(methodSpecification, parameterTypes); + if (parameters == null) { + if (isEmitErrors()) { + E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList())); + String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method), + methodSpecification.toSignatureString(method.getSimpleName().toString())); + invalidMethod.addError(message); + return invalidMethod; + } else { + return null; + } + } + + return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters)); + } + + private static String createActualSignature(MethodSpec spec, ExecutableElement method) { + StringBuilder b = new StringBuilder("("); + String sep = ""; + for (TypeMirror implicitType : spec.getImplicitRequiredTypes()) { + b.append(sep); + b.append("implicit " + Utils.getSimpleName(implicitType)); + sep = ", "; + } + for (VariableElement var : method.getParameters()) { + b.append(sep); + b.append(Utils.getSimpleName(var.asType())); + sep = ", "; + } + b.append(")"); + return b.toString(); + } + + private List parseParameters(MethodSpec spec, List parameterTypes) { + List parsedParams = new ArrayList<>(); + ConsumableListIterator types = new ConsumableListIterator<>(parameterTypes); + + // 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, false); + if (optionalParam != null) { + optionals.consume(optionalCount); + types.consume(); + parsedParams.add(optionalParam); + break; + } + optionalCount++; + } + if (oldIndex == types.getIndex()) { + // nothing found anymore skip optional + break; + } + } + + List typesWithImplicit = new ArrayList<>(spec.getImplicitRequiredTypes()); + typesWithImplicit.addAll(types.toList()); + types = new ConsumableListIterator<>(typesWithImplicit); + + 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; + } + break; + } + boolean implicit = types.getIndex() < spec.getImplicitRequiredTypes().size(); + ActualParameter resolvedParameter = matchParameter(required.get(), types.get(), template, specificationParameterIndex, implicit); + if (resolvedParameter == null) { + if (required.get().getCardinality() == Cardinality.MANY) { + required.consume(); + continue; + } + // direct mismatch but required -> error + return null; + } else { + parsedParams.add(resolvedParameter); + types.consume(); + if (required.get().getCardinality() == Cardinality.ONE) { + required.consume(); + specificationParameterIndex = 0; + } else if (required.get().getCardinality() == Cardinality.MANY) { + specificationParameterIndex++; + } + } + } + + if (!types.toList().isEmpty()) { + // additional types -> error + return null; + } + + if (!required.toList().isEmpty() && !spec.isVariableRequiredArguments()) { + // additional specifications -> error + return null; + } + + // success! + return parsedParams; + } + + private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int index, boolean implicit) { + TypeMirror resolvedType = mirror; + if (hasError(resolvedType)) { + resolvedType = context.resolveNotYetCompiledType(mirror, originalTemplate); + } + + if (!specification.matches(resolvedType)) { + return null; + } + + TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType); + if (resolvedTypeData != null) { + return new ActualParameter(specification, resolvedTypeData, index, implicit); + } else { + return new ActualParameter(specification, resolvedType, index, implicit); + } + } + + /* Helper class for parsing. */ + 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 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(); + } + } + + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.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 f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardData.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,46 @@ +/* + * 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.typesystem; + +import com.oracle.truffle.dsl.processor.node.*; +import com.oracle.truffle.dsl.processor.template.*; + +public class GuardData extends TemplateMethod { + + private final SpecializationData specialization; + + public GuardData(TemplateMethod method, SpecializationData specialization) { + super(method); + this.specialization = specialization; + } + + public SpecializationData getSpecialization() { + return specialization; + } + + @Override + public String toString() { + return getMethodName(); + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,98 @@ +/* + * 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.typesystem; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.node.*; +import com.oracle.truffle.dsl.processor.template.*; + +public class GuardParser extends NodeMethodParser { + + private final SpecializationData specialization; + private final String guardName; + + public GuardParser(ProcessorContext context, SpecializationData specialization, String guardName) { + super(context, specialization.getNode()); + this.specialization = specialization; + this.guardName = guardName; + setEmitErrors(false); + setParseNullOnError(false); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null); + spec.setVariableRequiredArguments(true); + spec.getRequired().clear(); + + for (ActualParameter parameter : specialization.getRequiredParameters()) { + ParameterSpec paramSpec = new ParameterSpec(parameter.getLocalName(), parameter.getType(), getNode().getTypeSystem().getGenericType()); + paramSpec.setSignature(true); + spec.addRequired(paramSpec); + } + + return spec; + } + + @Override + protected ParameterSpec createReturnParameterSpec() { + return new ParameterSpec("returnType", getContext().getType(boolean.class)); + } + + @Override + public boolean isParsable(ExecutableElement method) { + return method.getSimpleName().toString().equals(guardName); + } + + @Override + public GuardData create(TemplateMethod method) { + GuardData guard = new GuardData(method, specialization); + /* + * 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 { + newParameters.add(new ActualParameter(specializationParameter.getSpecification(), parameter.getTypeSystemType(), specializationParameter.getIndex(), parameter.isImplicit())); + } + } + guard.setParameters(newParameters); + + return guard; + } + + @Override + public Class getAnnotationType() { + return null; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastData.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,49 @@ +/* + * 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.typesystem; + +import com.oracle.truffle.dsl.processor.template.*; + +public class TypeCastData extends TemplateMethod { + + private final TypeData targetType; + private final TypeData sourceType; + + public TypeCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) { + super(method); + this.sourceType = sourceType; + this.targetType = targetType; + } + + public boolean isGeneric() { + return sourceType.isGeneric(); + } + + public TypeData getSourceType() { + return sourceType; + } + + public TypeData getTargetType() { + return targetType; + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,61 @@ +/* + * 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.typesystem; + +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.*; + +class TypeCastParser extends TypeSystemMethodParser { + + public TypeCastParser(ProcessorContext context, TypeSystemData typeSystem) { + super(context, typeSystem); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "as"); + if (targetType == null) { + return null; + } + MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", targetType.getPrimitiveType())); + spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors())); + return spec; + } + + @Override + public TypeCastData create(TemplateMethod method) { + TypeData targetType = findTypeByMethodName(method, "as"); + ActualParameter parameter = method.findParameter("valueValue"); + return new TypeCastData(method, parameter.getTypeSystemType(), targetType); + } + + @Override + public Class getAnnotationType() { + return TypeCast.class; + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckData.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,50 @@ +/* + * 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.typesystem; + +import com.oracle.truffle.dsl.processor.template.*; + +public class TypeCheckData extends TemplateMethod { + + private final TypeData checkedType; + private final TypeData valueType; + + public TypeCheckData(TemplateMethod method, TypeData checkedType, TypeData valueType) { + super(method); + this.checkedType = checkedType; + this.valueType = valueType; + } + + public boolean isGeneric() { + return valueType.isGeneric(); + } + + public TypeData getCheckedType() { + return checkedType; + } + + public TypeData getValueType() { + return valueType; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,63 @@ +/* + * 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.typesystem; + +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.*; + +class TypeCheckParser extends TypeSystemMethodParser { + + public TypeCheckParser(ProcessorContext context, TypeSystemData typeSystem) { + super(context, typeSystem); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "is"); + if (targetType == null) { + return null; + } + MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", getContext().getType(boolean.class))); + spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors())); + return spec; + } + + @Override + public TypeCheckData create(TemplateMethod method) { + TypeData checkedType = findTypeByMethodName(method, "is"); + assert checkedType != null; + ActualParameter parameter = method.findParameter("valueValue"); + assert parameter != null; + return new TypeCheckData(method, checkedType, parameter.getTypeSystemType()); + } + + @Override + public Class getAnnotationType() { + return TypeCheck.class; + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeData.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,130 @@ +/* + * 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.typesystem; + +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.template.*; + +public class TypeData extends MessageContainer { + + private final TypeSystemData typeSystem; + private final AnnotationValue annotationValue; + private final TypeMirror primitiveType; + private final TypeMirror boxedType; + + private final List typeCasts = new ArrayList<>(); + private final List typeChecks = new ArrayList<>(); + + public TypeData(TypeSystemData typeSystem, AnnotationValue value, TypeMirror primitiveType, TypeMirror boxedType) { + this.typeSystem = typeSystem; + this.annotationValue = value; + this.primitiveType = primitiveType; + this.boxedType = boxedType; + } + + @Override + public Element getMessageElement() { + return typeSystem.getMessageElement(); + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return typeSystem.getMessageAnnotation(); + } + + @Override + public AnnotationValue getMessageAnnotationValue() { + return annotationValue; + } + + void addTypeCast(TypeCastData typeCast) { + this.typeCasts.add(typeCast); + } + + void addTypeCheck(TypeCheckData typeCheck) { + this.typeChecks.add(typeCheck); + } + + public List getTypeCasts() { + return typeCasts; + } + + public List getTypeChecks() { + return typeChecks; + } + + public TypeSystemData getTypeSystem() { + return typeSystem; + } + + public TypeMirror getPrimitiveType() { + return primitiveType; + } + + public TypeMirror getBoxedType() { + return boxedType; + } + + public boolean isGeneric() { + return Utils.typeEquals(boxedType, getTypeSystem().getGenericType()); + } + + public boolean isVoid() { + if (getTypeSystem().getVoidType() == null) { + return false; + } + return Utils.typeEquals(boxedType, getTypeSystem().getVoidType().getBoxedType()); + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + Utils.getSimpleName(primitiveType) + "]"; + } + + public boolean equalsType(TypeData actualTypeData) { + return Utils.typeEquals(boxedType, actualTypeData.boxedType); + } + + public boolean needsCastTo(ProcessorContext context, TypeData targetType) { + if (this.equals(targetType)) { + return false; + } else if (targetType.isGeneric()) { + return false; + } else if (targetType.isVoid()) { + return false; + } else if (Utils.isAssignable(context, getPrimitiveType(), targetType.getPrimitiveType())) { + return false; + } + return true; + } + + public boolean isPrimitive() { + return Utils.isPrimitive(getPrimitiveType()); + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemCodeGenerator.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,180 @@ +/* + * 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.typesystem; + +import static com.oracle.truffle.dsl.processor.Utils.*; +import static javax.lang.model.element.Modifier.*; + +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.ast.*; +import com.oracle.truffle.dsl.processor.template.*; + +public class TypeSystemCodeGenerator extends CompilationUnitFactory { + + public TypeSystemCodeGenerator(ProcessorContext context) { + super(context); + } + + public static String isTypeMethodName(TypeData type) { + return "is" + Utils.getTypeId(type.getBoxedType()); + } + + public static String asTypeMethodName(TypeData type) { + return "as" + Utils.getTypeId(type.getBoxedType()); + } + + public static String expectTypeMethodName(TypeData type) { + return "expect" + Utils.getTypeId(type.getBoxedType()); + } + + /** + * Finds the generated singleton field for a TypeSytemData instance. TypeSystemCodeGenerator + * must be applied to the TypeSystemData model before use. + */ + public static VariableElement findSingleton(ProcessorContext context, TypeSystemData typeSystem) { + TypeMirror type = context.findGeneratedClassBySimpleName(TypeClassFactory.typeName(typeSystem), typeSystem); + return Utils.findDeclaredField(type, TypeClassFactory.singletonName(typeSystem.getTemplateType().asType())); + } + + @Override + protected void createChildren(TypeSystemData m) { + add(new TypeClassFactory(context), m); + } + + protected static class TypeClassFactory extends ClassElementFactory { + + private static final String LOCAL_VALUE = "value"; + + public TypeClassFactory(ProcessorContext context) { + super(context); + } + + @Override + public CodeTypeElement create(TypeSystemData typeSystem) { + String name = typeName(typeSystem); + CodeTypeElement clazz = createClass(typeSystem, modifiers(PUBLIC), name, typeSystem.getTemplateType().asType(), false); + + clazz.add(createConstructorUsingFields(modifiers(PROTECTED), clazz)); + CodeVariableElement singleton = createSingleton(clazz); + clazz.add(singleton); + + for (TypeData type : typeSystem.getTypes()) { + if (!type.isGeneric()) { + CodeExecutableElement isType = createIsTypeMethod(type); + if (isType != null) { + clazz.add(isType); + } + CodeExecutableElement asType = createAsTypeMethod(type); + if (asType != null) { + clazz.add(asType); + } + + for (TypeData sourceType : collectExpectSourceTypes(type)) { + CodeExecutableElement expect = createExpectTypeMethod(type, sourceType); + if (expect != null) { + clazz.add(expect); + } + } + } + } + + return clazz; + } + + private static List collectExpectSourceTypes(TypeData type) { + Set sourceTypes = new HashSet<>(); + sourceTypes.add(type.getTypeSystem().getGenericTypeData()); + for (TypeCastData cast : type.getTypeCasts()) { + sourceTypes.add(cast.getSourceType()); + } + for (TypeCheckData cast : type.getTypeChecks()) { + sourceTypes.add(cast.getCheckedType()); + } + return new ArrayList<>(sourceTypes); + } + + private static String typeName(TypeSystemData typeSystem) { + String name = getSimpleName(typeSystem.getTemplateType()); + return name + "Gen"; + } + + private static String singletonName(TypeMirror type) { + return createConstantName(getSimpleName(type)); + } + + private CodeVariableElement createSingleton(CodeTypeElement clazz) { + CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(getModel().getTemplateType().asType())); + field.createInitBuilder().startNew(clazz.asType()).end(); + return field; + } + + private CodeExecutableElement createIsTypeMethod(TypeData type) { + if (!type.getTypeChecks().isEmpty()) { + return null; + } + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(type)); + method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); + + CodeTreeBuilder body = method.createBuilder(); + body.startReturn().instanceOf(LOCAL_VALUE, type.getBoxedType()).end(); + + return method; + } + + private CodeExecutableElement createAsTypeMethod(TypeData type) { + if (!type.getTypeCasts().isEmpty()) { + return null; + } + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asTypeMethodName(type)); + method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); + + CodeTreeBuilder body = method.createBuilder(); + body.startAssert().startCall(isTypeMethodName(type)).string(LOCAL_VALUE).end().end(); + body.startReturn().cast(type.getPrimitiveType(), body.create().string(LOCAL_VALUE).getTree()).end(); + + return method; + } + + private CodeExecutableElement createExpectTypeMethod(TypeData expectedType, TypeData sourceType) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), expectedType.getPrimitiveType(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType)); + method.addParameter(new CodeVariableElement(sourceType.getPrimitiveType(), LOCAL_VALUE)); + method.addThrownType(getContext().getTruffleTypes().getUnexpectedValueException()); + + CodeTreeBuilder body = method.createBuilder(); + body.startIf().startCall(null, TypeSystemCodeGenerator.isTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end().startBlock(); + body.startReturn().startCall(null, TypeSystemCodeGenerator.asTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end(); + body.end(); // if-block + body.startThrow().startNew(getContext().getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end(); + + return method; + } + + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,147 @@ +/* + * 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.typesystem; + +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.template.*; + +public class TypeSystemData extends Template { + + private List types; + private List primitiveTypeMirrors = new ArrayList<>(); + private List boxedTypeMirrors = new ArrayList<>(); + + private TypeMirror genericType; + private TypeData voidType; + + public TypeSystemData(TypeElement templateType, AnnotationMirror annotation) { + super(templateType, null, annotation); + } + + @Override + public TypeSystemData getTypeSystem() { + return this; + } + + void setTypes(List types) { + this.types = types; + if (types != null) { + for (TypeData typeData : types) { + primitiveTypeMirrors.add(typeData.getPrimitiveType()); + boxedTypeMirrors.add(typeData.getBoxedType()); + } + } + } + + void setGenericType(TypeMirror genericType) { + this.genericType = genericType; + } + + void setVoidType(TypeData voidType) { + this.voidType = voidType; + } + + @Override + protected List findChildContainers() { + List sinks = new ArrayList<>(); + if (types != null) { + sinks.addAll(types); + } + return sinks; + } + + public boolean isGeneric(TypeMirror type) { + return Utils.typeEquals(getGenericType(), type); + } + + public TypeData getVoidType() { + return voidType; + } + + public List getBoxedTypeMirrors() { + return boxedTypeMirrors; + } + + public List getPrimitiveTypeMirrors() { + return primitiveTypeMirrors; + } + + public List getTypes() { + return types; + } + + public TypeMirror getGenericType() { + return genericType; + } + + public TypeData getGenericTypeData() { + TypeData result = types.get(types.size() - 1); + assert result.getBoxedType() == genericType; + return result; + } + + public TypeData findType(String simpleName) { + for (TypeData type : types) { + if (Utils.getSimpleName(type.getBoxedType()).equals(simpleName)) { + return type; + } + } + return null; + } + + public TypeData findTypeData(TypeMirror type) { + if (Utils.typeEquals(voidType.getPrimitiveType(), type)) { + return voidType; + } + + int index = findType(type); + if (index == -1) { + return null; + } + return types.get(index); + } + + public int findType(TypeData typeData) { + return findType(typeData.getPrimitiveType()); + } + + public int findType(TypeMirror type) { + for (int i = 0; i < types.size(); i++) { + if (Utils.typeEquals(types.get(i).getPrimitiveType(), type)) { + return i; + } + } + return -1; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[template = " + Utils.getSimpleName(getTemplateType()) + ", types = " + types + "]"; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemMethodParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemMethodParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,66 @@ +/* + * 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.typesystem; + +import javax.lang.model.element.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.template.*; + +abstract class TypeSystemMethodParser extends TemplateMethodParser { + + public TypeSystemMethodParser(ProcessorContext context, TypeSystemData typeSystem) { + super(context, typeSystem); + } + + @Override + public final boolean isParsable(ExecutableElement method) { + return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; + } + + protected TypeData findTypeByMethodName(String methodName, String prefix) { + String typeName = methodName.substring(prefix.length(), methodName.length()); + TypeData type = getTypeSystem().findType(typeName); + return type; + } + + protected TypeData findTypeByMethodName(TemplateMethod method, String prefix) { + String methodName = method.getMethodName(); + if (!methodName.startsWith(prefix)) { + String annotationName = Utils.getSimpleName(method.getMessageAnnotation().getAnnotationType()); + method.addError("Methods annotated with %s must match the pattern '%s'.", annotationName, String.format("%s${typeName}", prefix)); + return null; + } + String typeName = methodName.substring(prefix.length(), methodName.length()); + TypeData type = getTypeSystem().findType(typeName); + if (type == null) { + String annotationName = TypeSystem.class.getSimpleName(); + method.addError("Type '%s' is not declared in this @%s.", typeName, annotationName); + return null; + } + + return type; + } + +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java Mon Jul 01 20:58:32 2013 +0200 @@ -0,0 +1,277 @@ +/* + * 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.typesystem; + +import static com.oracle.truffle.dsl.processor.Utils.*; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +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.template.*; + +public class TypeSystemParser extends TemplateParser { + + public static final List> ANNOTATIONS = Arrays.asList(TypeSystem.class); + + public TypeSystemParser(ProcessorContext c) { + super(c); + } + + @Override + public Class getAnnotationType() { + return TypeSystem.class; + } + + @Override + protected TypeSystemData parse(Element element, AnnotationMirror mirror) { + TypeElement templateType = (TypeElement) element; + AnnotationMirror templateTypeAnnotation = mirror; + TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation); + + // annotation type on class path!? + TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName()); + if (annotationTypeElement == null) { + typeSystem.addError("Required class %s is not on the classpath.", getAnnotationType().getName()); + } + if (templateType.getModifiers().contains(Modifier.PRIVATE)) { + typeSystem.addError("A @%s must have at least package protected visibility.", getAnnotationType().getName()); + } + + if (templateType.getModifiers().contains(Modifier.FINAL)) { + typeSystem.addError("The @%s must not be final.", getAnnotationType().getName()); + } + if (typeSystem.hasErrors()) { + return typeSystem; + } + + typeSystem.setTypes(parseTypes(typeSystem)); + if (typeSystem.getTypes() == null) { + return typeSystem; + } + + TypeMirror genericType = context.getType(Object.class); + TypeData voidType = new TypeData(typeSystem, null, context.getType(void.class), context.getType(Void.class)); + + typeSystem.setGenericType(genericType); + typeSystem.setVoidType(voidType); + + verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class); + + List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType)); + + List casts = new TypeCastParser(context, typeSystem).parse(elements); + List checks = new TypeCheckParser(context, typeSystem).parse(elements); + + if (casts == null || checks == null) { + return typeSystem; + } + + for (TypeCheckData check : checks) { + check.getCheckedType().addTypeCheck(check); + } + + for (TypeCastData cast : casts) { + cast.getTargetType().addTypeCast(cast); + } + + verifyGenericTypeChecksAndCasts(typeSystem); + verifyMethodSignatures(typeSystem); + verifyNamesUnique(typeSystem); + + return typeSystem; + } + + private static void verifyGenericTypeChecksAndCasts(TypeSystemData typeSystem) { + for (TypeData type : typeSystem.getTypes()) { + if (!type.getTypeChecks().isEmpty()) { + boolean hasGeneric = false; + for (TypeCheckData typeCheck : type.getTypeChecks()) { + if (typeCheck.isGeneric()) { + hasGeneric = true; + break; + } + } + if (!hasGeneric) { + type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.", + TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(), + Object.class.getSimpleName()); + } + } + if (!type.getTypeCasts().isEmpty()) { + boolean hasGeneric = false; + for (TypeCastData typeCast : type.getTypeCasts()) { + if (typeCast.isGeneric()) { + hasGeneric = true; + break; + } + } + if (!hasGeneric) { + type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.", + TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(), + Object.class.getSimpleName()); + } + } + } + } + + private List parseTypes(TypeSystemData typeSystem) { + List types = new ArrayList<>(); + List typeMirrors = Utils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value"); + if (typeMirrors.isEmpty()) { + typeSystem.addError("At least one type must be defined."); + return types; + } + + final AnnotationValue annotationValue = Utils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "value"); + final TypeMirror objectType = context.getType(Object.class); + + for (TypeMirror primitiveType : typeMirrors) { + TypeMirror boxedType = Utils.boxType(context, primitiveType); + TypeData typeData = new TypeData(typeSystem, annotationValue, primitiveType, boxedType); + + if (isPrimitiveWrapper(primitiveType)) { + typeData.addError("Types must not contain primitive wrapper types."); + } + + if (Utils.typeEquals(boxedType, objectType)) { + typeData.addError("Types must not contain the generic type java.lang.Object."); + } + + types.add(typeData); + } + + verifyTypeOrder(types); + + types.add(new TypeData(typeSystem, annotationValue, objectType, objectType)); + + return types; + } + + private static void verifyTypeOrder(List types) { + Map> invalidTypes = new HashMap<>(); + + for (int i = types.size() - 1; i >= 0; i--) { + TypeData typeData = types.get(i); + TypeMirror type = typeData.getBoxedType(); + if (invalidTypes.containsKey(Utils.getQualifiedName(type))) { + typeData.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(Utils.getQualifiedName(type)), Utils.getQualifiedName(type)); + } + List nextInvalidTypes = Utils.getQualifiedSuperTypeNames(Utils.fromTypeMirror(type)); + nextInvalidTypes.add(getQualifiedName(type)); + + for (String qualifiedName : nextInvalidTypes) { + List inheritedTypes = invalidTypes.get(qualifiedName); + if (inheritedTypes == null) { + inheritedTypes = new ArrayList<>(); + invalidTypes.put(qualifiedName, inheritedTypes); + } + inheritedTypes.add(Utils.getQualifiedName(typeData.getBoxedType())); + } + } + } + + private boolean isPrimitiveWrapper(TypeMirror type) { + Types types = context.getEnvironment().getTypeUtils(); + for (TypeKind kind : TypeKind.values()) { + if (!kind.isPrimitive()) { + continue; + } + if (Utils.typeEquals(type, types.boxedClass(types.getPrimitiveType(kind)).asType())) { + return true; + } + } + return false; + } + + private void verifyMethodSignatures(TypeSystemData typeSystem) { + Set generatedIsMethodNames = new HashSet<>(); + Set generatedAsMethodNames = new HashSet<>(); + Set generatedExpectMethodNames = new HashSet<>(); + + for (TypeData typeData : typeSystem.getTypes()) { + generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData)); + generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData)); + generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData)); + } + + List methods = ElementFilter.methodsIn(typeSystem.getTemplateType().getEnclosedElements()); + for (ExecutableElement method : methods) { + if (method.getModifiers().contains(Modifier.PRIVATE)) { + // will not conflict overridden methods + continue; + } else if (method.getParameters().size() != 1) { + continue; + } + String methodName = method.getSimpleName().toString(); + if (generatedIsMethodNames.contains(methodName)) { + verifyIsMethod(typeSystem, method); + } else if (generatedAsMethodNames.contains(methodName)) { + verifyAsMethod(typeSystem, method); + } else if (generatedExpectMethodNames.contains(methodName)) { + verifyExpectMethod(typeSystem); + } + } + } + + private boolean verifyIsMethod(TypeSystemData typeSystem, ExecutableElement method) { + AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCheck.class); + if (mirror == null) { + typeSystem.addError("Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName()); + return false; + } + return true; + } + + private boolean verifyAsMethod(TypeSystemData typeSystem, ExecutableElement method) { + AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCast.class); + if (mirror == null) { + typeSystem.addError("Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName()); + return false; + } + return true; + } + + private static boolean verifyExpectMethod(TypeSystemData typeSystem) { + typeSystem.addError("Method starting with the pattern expect${typeName} must not be declared manually."); + return false; + } + + private static void verifyNamesUnique(TypeSystemData typeSystem) { + List types = typeSystem.getTypes(); + for (int i = 0; i < types.size(); i++) { + for (int j = i + 1; j < types.size(); j++) { + String name1 = Utils.getSimpleName(types.get(i).getBoxedType()); + String name2 = Utils.getSimpleName(types.get(j).getBoxedType()); + if (name1.equalsIgnoreCase(name2)) { + typeSystem.addError("Two types result in the same name: %s, %s.", name1, name2); + } + } + } + } +} diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLNode.java Mon Jul 01 20:32:20 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLNode.java Mon Jul 01 20:58:32 2013 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.truffle.sl; -import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.nodes.*; @TypeSystemReference(SLTypes.class) diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java Mon Jul 01 20:32:20 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java Mon Jul 01 20:58:32 2013 +0200 @@ -24,7 +24,7 @@ import java.math.*; -import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.dsl.*; @TypeSystem({int.class, BigInteger.class, boolean.class, String.class}) public class SLTypes { diff -r f43eb2f1bbbc -r 79041ab43660 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 Mon Jul 01 20:32:20 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java Mon Jul 01 20:58:32 2013 +0200 @@ -25,7 +25,7 @@ import java.math.*; import com.oracle.truffle.api.*; -import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.dsl.*; public abstract class ArithmeticNode extends BinaryNode { diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BigIntegerLiteralNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BigIntegerLiteralNode.java Mon Jul 01 20:32:20 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BigIntegerLiteralNode.java Mon Jul 01 20:58:32 2013 +0200 @@ -24,7 +24,7 @@ import java.math.*; -import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.dsl.*; public abstract class BigIntegerLiteralNode extends TypedNode { diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BinaryNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BinaryNode.java Mon Jul 01 20:32:20 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BinaryNode.java Mon Jul 01 20:58:32 2013 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.truffle.sl.nodes; -import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.dsl.*; @NodeChildren({@NodeChild("leftNode"), @NodeChild("rightNode")}) public abstract class BinaryNode extends TypedNode { diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java Mon Jul 01 20:32:20 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java Mon Jul 01 20:58:32 2013 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.truffle.sl.nodes; -import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; @NodeChild(value = "conditionNode", type = ConditionNode.class) diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IntegerLiteralNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IntegerLiteralNode.java Mon Jul 01 20:32:20 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IntegerLiteralNode.java Mon Jul 01 20:58:32 2013 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.truffle.sl.nodes; -import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.dsl.*; public abstract class IntegerLiteralNode extends TypedNode { diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LessThanNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LessThanNode.java Mon Jul 01 20:32:20 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LessThanNode.java Mon Jul 01 20:58:32 2013 +0200 @@ -24,7 +24,7 @@ import java.math.*; -import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.dsl.*; public abstract class LessThanNode extends BinaryNode { diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LogicalAndNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LogicalAndNode.java Mon Jul 01 20:32:20 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LogicalAndNode.java Mon Jul 01 20:58:32 2013 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.truffle.sl.nodes; -import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.dsl.*; @SuppressWarnings("unused") public abstract class LogicalAndNode extends BinaryNode { diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java Mon Jul 01 20:32:20 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java Mon Jul 01 20:58:32 2013 +0200 @@ -24,7 +24,7 @@ import java.io.*; -import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.dsl.*; @NodeChild(type = TypedNode.class) public abstract class PrintNode extends StatementNode { diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadLocalNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadLocalNode.java Mon Jul 01 20:32:20 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadLocalNode.java Mon Jul 01 20:58:32 2013 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.truffle.sl.nodes; -import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; public abstract class ReadLocalNode extends FrameSlotNode { diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/StringLiteralNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/StringLiteralNode.java Mon Jul 01 20:32:20 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/StringLiteralNode.java Mon Jul 01 20:58:32 2013 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.truffle.sl.nodes; -import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.dsl.*; public abstract class StringLiteralNode extends TypedNode { diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TernaryNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TernaryNode.java Mon Jul 01 20:32:20 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TernaryNode.java Mon Jul 01 20:58:32 2013 +0200 @@ -23,7 +23,8 @@ package com.oracle.truffle.sl.nodes; import java.math.*; -import com.oracle.truffle.api.codegen.*; + +import com.oracle.truffle.api.dsl.*; @SuppressWarnings("unused") @NodeChildren({@NodeChild(value = "conditionNode", type = ConditionNode.class), @NodeChild("ifPartNode"), @NodeChild("elsePartNode")}) diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TimeNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TimeNode.java Mon Jul 01 20:32:20 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TimeNode.java Mon Jul 01 20:58:32 2013 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.truffle.sl.nodes; -import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.dsl.*; public abstract class TimeNode extends TypedNode { diff -r f43eb2f1bbbc -r 79041ab43660 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java Mon Jul 01 20:32:20 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java Mon Jul 01 20:58:32 2013 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.truffle.sl.nodes; -import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; @NodeChild(value = "rightNode", type = TypedNode.class) diff -r f43eb2f1bbbc -r 79041ab43660 mx/projects --- a/mx/projects Mon Jul 01 20:32:20 2013 +0200 +++ b/mx/projects Mon Jul 01 20:58:32 2013 +0200 @@ -498,38 +498,38 @@ project@com.oracle.truffle.api.test@javaCompliance=1.7 project@com.oracle.truffle.api.test@workingSets=API,Truffle,Test -# truffle.api.codegen -project@com.oracle.truffle.api.codegen@subDir=graal -project@com.oracle.truffle.api.codegen@sourceDirs=src -project@com.oracle.truffle.api.codegen@dependencies=com.oracle.truffle.api -project@com.oracle.truffle.api.codegen@checkstyle=com.oracle.graal.graph -project@com.oracle.truffle.api.codegen@javaCompliance=1.7 -project@com.oracle.truffle.api.codegen@workingSets=API,Truffle,Codegen +# truffle.api.dsl +project@com.oracle.truffle.api.dsl@subDir=graal +project@com.oracle.truffle.api.dsl@sourceDirs=src +project@com.oracle.truffle.api.dsl@dependencies=com.oracle.truffle.api +project@com.oracle.truffle.api.dsl@checkstyle=com.oracle.graal.graph +project@com.oracle.truffle.api.dsl@javaCompliance=1.7 +project@com.oracle.truffle.api.dsl@workingSets=API,Truffle,Codegen -# truffle.api.codegen.test -project@com.oracle.truffle.api.codegen.test@subDir=graal -project@com.oracle.truffle.api.codegen.test@sourceDirs=src -project@com.oracle.truffle.api.codegen.test@dependencies=com.oracle.truffle.api.codegen,JUNIT -project@com.oracle.truffle.api.codegen.test@checkstyle=com.oracle.graal.graph -project@com.oracle.truffle.api.codegen.test@javaCompliance=1.7 -project@com.oracle.truffle.api.codegen.test@annotationProcessors=com.oracle.truffle.codegen.processor -project@com.oracle.truffle.api.codegen.test@workingSets=API,Truffle,Codegen,Test +# truffle.api.dsl.test +project@com.oracle.truffle.api.dsl.test@subDir=graal +project@com.oracle.truffle.api.dsl.test@sourceDirs=src +project@com.oracle.truffle.api.dsl.test@dependencies=com.oracle.truffle.api.dsl,JUNIT +project@com.oracle.truffle.api.dsl.test@checkstyle=com.oracle.graal.graph +project@com.oracle.truffle.api.dsl.test@javaCompliance=1.7 +project@com.oracle.truffle.api.dsl.test@annotationProcessors=com.oracle.truffle.dsl.processor +project@com.oracle.truffle.api.dsl.test@workingSets=API,Truffle,Codegen,Test -# truffle.codegen.processor -project@com.oracle.truffle.codegen.processor@subDir=graal -project@com.oracle.truffle.codegen.processor@sourceDirs=src -project@com.oracle.truffle.codegen.processor@dependencies=com.oracle.truffle.api.codegen -project@com.oracle.truffle.codegen.processor@checkstyle=com.oracle.graal.graph -project@com.oracle.truffle.codegen.processor@javaCompliance=1.7 -project@com.oracle.truffle.codegen.processor@workingSets=Truffle,Codegen +# truffle.dsl.processor +project@com.oracle.truffle.dsl.processor@subDir=graal +project@com.oracle.truffle.dsl.processor@sourceDirs=src +project@com.oracle.truffle.dsl.processor@dependencies=com.oracle.truffle.api.dsl +project@com.oracle.truffle.dsl.processor@checkstyle=com.oracle.graal.graph +project@com.oracle.truffle.dsl.processor@javaCompliance=1.7 +project@com.oracle.truffle.dsl.processor@workingSets=Truffle,Codegen # truffle.sl project@com.oracle.truffle.sl@subDir=graal project@com.oracle.truffle.sl@sourceDirs=src -project@com.oracle.truffle.sl@dependencies=com.oracle.truffle.api.codegen +project@com.oracle.truffle.sl@dependencies=com.oracle.truffle.api.dsl project@com.oracle.truffle.sl@checkstyle=com.oracle.graal.graph project@com.oracle.truffle.sl@javaCompliance=1.7 -project@com.oracle.truffle.sl@annotationProcessors=com.oracle.truffle.codegen.processor +project@com.oracle.truffle.sl@annotationProcessors=com.oracle.truffle.dsl.processor project@com.oracle.truffle.sl@workingSets=Truffle,SimpleLanguage # truffle.sl.test