# HG changeset patch # User Christian Humer # Date 1421978123 -3600 # Node ID 08aa0372dad4e604113321514075a209ff7b146e # Parent ae81dd154fb6a5c41e77089e5a0fb00ecd38841d Truffle-DSL: implement new guard expression syntax. diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java Fri Jan 23 02:55:23 2015 +0100 @@ -51,11 +51,11 @@ return true; } - @Specialization(guards = {"guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1", - "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2", - "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1", - "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2", - "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1"}) + @Specialization(guards = {"guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1()", + "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2()", + "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1()", + "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2()", + "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1()"}) public int execute() { return 42; } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java Fri Jan 23 02:55:23 2015 +0100 @@ -100,7 +100,7 @@ return a == 0; } - @Specialization(guards = "isZero") + @Specialization(guards = "isZero(a)") int f1(int a) { return a + 1; } @@ -142,17 +142,17 @@ return a > 0; } - @Implies("isGreaterZero") + @Implies("isGreaterZero(a)") static boolean isOne(int a) { return a == 1; } - @Specialization(guards = {"isOne"}) + @Specialization(guards = {"isOne(a)"}) int f1(int a) { return a + 1; } - @Specialization(contains = "f1", guards = {"isGreaterZero"}) + @Specialization(contains = "f1", guards = {"isGreaterZero(a)"}) int f2(int a) { if (a == 1) { return 2; @@ -190,21 +190,17 @@ @NodeChild("a") abstract static class Contains4 extends ValueNode { - static boolean isGreaterEqualZero(int a) { - return a >= 0; - } - @Implies("isGreaterEqualZero") static boolean isOne(int a) { return a == 1; } - @Specialization(guards = {"isOne"}) + @Specialization(guards = "isOne(a)") int f0(int a) { return 1; } - @Specialization(contains = "f0", guards = {"isGreaterEqualZero"}) + @Specialization(contains = "f0", guards = "a >= 0") int f1(int a) { return a; } @@ -329,7 +325,7 @@ return a; } - @ExpectError({"Specialization is not reachable. It is shadowed by f0(double).", "The contained specialization 'f0' is not fully compatible.%"}) + @ExpectError({"Specialization is not reachable. It is shadowed by f0(double)."}) @Specialization(contains = "f0") int f1(int a) { // implicit type return a; @@ -343,7 +339,6 @@ return a; } - @ExpectError("The contained specialization 'f0' is not fully compatible.%") @Specialization(contains = "f0") Object f1(int a, Object b) { return a; @@ -357,7 +352,6 @@ return a; } - @ExpectError("The contained specialization 'f0' is not fully compatible.%") @Specialization(contains = "f0") Object f1(int a, double b) { // implicit type return a; @@ -370,7 +364,7 @@ return true; } - @Specialization(guards = "g1") + @Specialization(guards = "g1()") Object f0() { return null; } @@ -392,8 +386,8 @@ return null; } - @ExpectError({"Specialization is not reachable. It is shadowed by f0().", "The contained specialization 'f0' is not fully compatible.%"}) - @Specialization(guards = "g1", contains = "f0") + @ExpectError({"Specialization is not reachable. It is shadowed by f0()."}) + @Specialization(guards = "g1()", contains = "f0") Object f1() { return null; } @@ -405,13 +399,12 @@ return true; } - @Specialization(guards = "g1") + @Specialization(guards = "g1()") Object f0() { return null; } - @ExpectError({"The contained specialization 'f0' is not fully compatible.%"}) - @Specialization(guards = "!g1", contains = "f0") + @Specialization(guards = "!g1()", contains = "f0") Object f1() { return null; } @@ -427,13 +420,12 @@ return true; } - @Specialization(guards = "g1") + @Specialization(guards = "g1()") Object f0() { return null; } - @ExpectError({"The contained specialization 'f0' is not fully compatible.%"}) - @Specialization(guards = "g2", contains = "f0") + @Specialization(guards = "g2()", contains = "f0") Object f1() { return null; } @@ -450,12 +442,12 @@ return true; } - @Specialization(guards = "g1") + @Specialization(guards = "g1()") Object f0() { return null; } - @Specialization(guards = "g2", contains = "f0") + @Specialization(guards = "g2()", contains = "f0") Object f1() { return null; } @@ -472,12 +464,12 @@ return true; } - @Specialization(guards = "g1") + @Specialization(guards = "g1()") Object f0() { return null; } - @Specialization(guards = "!g2", contains = "f0") + @Specialization(guards = "!g2()", contains = "f0") Object f1() { return null; } @@ -493,12 +485,12 @@ return true; } - @Specialization(guards = {"g1", "g2"}) + @Specialization(guards = {"g1()", "g2()"}) Object f0() { return null; } - @Specialization(guards = "g2", contains = "f0") + @Specialization(guards = "g2()", contains = "f0") Object f1() { return null; } @@ -518,36 +510,6 @@ } } - @NodeAssumptions("a1") - abstract static class ContainsAssumption2 extends ValueNode { - - @Specialization - Object f0() { - return null; - } - - @ExpectError({"Specialization is not reachable. It is shadowed by f0().", "The contained specialization 'f0' is not fully compatible.%"}) - @Specialization(contains = "f0", assumptions = "a1") - Object f1() { - return null; - } - } - - @NodeAssumptions({"a1", "a2"}) - abstract static class ContainsAssumption3 extends ValueNode { - - @Specialization(assumptions = "a1") - Object f0() { - return null; - } - - @ExpectError({"The contained specialization 'f0' is not fully compatible.%"}) - @Specialization(contains = "f0", assumptions = "a2") - Object f1() { - return null; - } - } - @NodeAssumptions({"a1", "a2"}) abstract static class ContainsAssumption4 extends ValueNode { @@ -619,20 +581,12 @@ @NodeChild("a") static class PolymorphicToMonomorphic0 extends ValueNode { - boolean isOne(int a) { - return a == 1; - } - - boolean isTwo(int a) { - return a == 2; - } - - @Specialization(guards = "isOne") + @Specialization(guards = "a == 1") int do1(int a) { return a; } - @Specialization(guards = "isTwo") + @Specialization(guards = "a == 2") int do2(int a) { return a; } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java Fri Jan 23 02:55:23 2015 +0100 @@ -104,7 +104,7 @@ return "(int)"; } - @Specialization(guards = "notInt") + @Specialization(guards = "notInt(a)") String f2(Object a) { return "(object)"; } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java Fri Jan 23 02:55:23 2015 +0100 @@ -36,7 +36,7 @@ @NodeChild("a") static class ImportGuards0 extends ValueNode { - @Specialization(guards = "staticGuard") + @Specialization(guards = "staticGuard(a)") int f0(int a) { return a; } @@ -46,26 +46,26 @@ @ImportGuards(Imports0.class) static class ImportGuards1 extends ValueNode { - @ExpectError("No compatible guard with method name 'nonStaticGuard' found.") - @Specialization(guards = "nonStaticGuard") + @ExpectError("Error parsing expression 'nonStaticGuard(a)': The method nonStaticGuard is undefined for the enclosing scope.") + @Specialization(guards = "nonStaticGuard(a)") int f1(int a) { return a; } - @ExpectError("No compatible guard with method name 'protectedGuard' found.") - @Specialization(guards = "protectedGuard") + @ExpectError("Error parsing expression 'protectedGuard(a)': The method protectedGuard is undefined for the enclosing scope.") + @Specialization(guards = "protectedGuard(a)") int f2(int a) { return a; } - @ExpectError("No compatible guard with method name 'packageGuard' found.") - @Specialization(guards = "packageGuard") + @ExpectError("Error parsing expression 'packageGuard(a)': The method packageGuard is undefined for the enclosing scope.") + @Specialization(guards = "packageGuard(a)") int f3(int a) { return a; } - @ExpectError("No compatible guard with method name 'privateGuard' found.") - @Specialization(guards = "privateGuard") + @ExpectError("Error parsing expression 'privateGuard(a)': The method privateGuard is undefined for the enclosing scope.") + @Specialization(guards = "privateGuard(a)") int f4(int a) { return a; } @@ -159,7 +159,7 @@ return a == 1; } - @Specialization(guards = "staticGuard") + @Specialization(guards = "staticGuard(a)") int f0(int a) { return a; } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java Fri Jan 23 02:55:23 2015 +0100 @@ -30,20 +30,12 @@ @NodeChild("a") static class InsertBefore1Base extends ValueNode { - boolean g1(int a) { - return a == 1; - } - - boolean g2(int a) { - return a == 2; - } - - @Specialization(guards = "g1") + @Specialization(guards = "a == 1") int f1(int a) { return a; } - @Specialization(guards = "g2") + @Specialization(guards = "a == 2") int f3(int a) { return a; } @@ -63,11 +55,7 @@ @NodeChild("a") static class InsertBefore1T2 extends InsertBefore1Base { - boolean g0(int a) { - return a == 0; - } - - @Specialization(guards = "g0", insertBefore = "f1") + @Specialization(guards = "a == 0", insertBefore = "f1") int f0(int a) { return a; } @@ -77,11 +65,7 @@ @NodeChild("a") static class InsertBefore1T3 extends InsertBefore1Base { - boolean g0(int a) { - return a == 0; - } - - @Specialization(guards = "g0", insertBefore = "f3") + @Specialization(guards = "a == 0", insertBefore = "f3") int f0(int a) { return a; } @@ -93,10 +77,6 @@ "Method f1(int) at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int)."}) static class InsertBefore1T4 extends InsertBefore1Base { - boolean g0(int a) { - return a == 0; - } - @Specialization(insertBefore = "f1") int f0(int a) { return a; @@ -126,7 +106,7 @@ return a == 0; } - @Specialization(insertBefore = "f1", guards = "g0") + @Specialization(insertBefore = "f1", guards = "a == 0") int f0(int a) { return a; } @@ -136,11 +116,7 @@ @NodeChild("a") static class InsertBefore1T6part2 extends InsertBefore1T6part1 { - boolean g(int a) { - return a == 0; - } - - @Specialization(insertBefore = "f0", guards = "g") + @Specialization(insertBefore = "f0", guards = "a == 3") int f(int a) { return a; } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java Fri Jan 23 02:55:23 2015 +0100 @@ -72,7 +72,7 @@ return value0 != Integer.MAX_VALUE; } - @Specialization(guards = "g") + @Specialization(guards = "g(value0)") int f1(int value0) { specializedInvocations++; return value0 + 1; @@ -107,7 +107,7 @@ return globalFlag; } - @Specialization(guards = "globalFlagGuard") + @Specialization(guards = "globalFlagGuard()") int f1(Object value0) { return 41; } @@ -132,7 +132,7 @@ return true; } - @Specialization(guards = "baseGuard") + @Specialization(guards = "baseGuard(value0)") int doSpecialized(BExtendsAbstract value0) { return 42; } @@ -145,8 +145,7 @@ return true; } - @Specialization(guards = "baseGuard") - @ExpectError("No guard with name 'baseGuard' matched the required signature.%") + @Specialization(guards = "baseGuard(value0)") int doSpecialized(String value0) { return 42; } @@ -166,7 +165,7 @@ return true; } - @Specialization(guards = "baseGuard") + @Specialization(guards = "baseGuard(value0)") int doSpecialized(int value0) { return value0; } @@ -186,7 +185,7 @@ return true; } - @Specialization(guards = "baseGuard") + @Specialization(guards = "baseGuard(value0)") int doSpecialized(int value0) { return value0; } @@ -210,7 +209,7 @@ return true; } - @Specialization(guards = "guard") + @Specialization(guards = "guard(value0)") int doSpecialized(int value0) { return value0; } @@ -233,7 +232,7 @@ return true; } - @Specialization(guards = "guard") + @Specialization(guards = "guard(value0)") int doSpecialized(BExtendsAbstract value0) { return 42; } @@ -261,7 +260,7 @@ return true; } - @Specialization(guards = "guard") + @Specialization(guards = "guard(value0)") int doSpecialized(BExtendsAbstract value0) { return 42; } @@ -274,7 +273,7 @@ return false; } - @Specialization(guards = "guard") + @Specialization(guards = "guard(value0)") int doSpecialized(BExtendsAbstract value0) { return 42; } @@ -283,7 +282,7 @@ @NodeChildren({@NodeChild("a"), @NodeChild("b")}) abstract static class TestGuardResolve5 extends ValueNode { - @Specialization(guards = "guard") + @Specialization(guards = "guard(left, right)") int add(Interface left, Interface right) { return 42; } @@ -308,12 +307,12 @@ return true; } - @Specialization(guards = "guard") + @Specialization(guards = "guard(value0)") BExtendsAbstract do1(BExtendsAbstract value0) { return value0; } - @Specialization(guards = "guard") + @Specialization(guards = "guard(value0)") CExtendsAbstract do2(CExtendsAbstract value0) { return value0; } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java Fri Jan 23 02:55:23 2015 +0100 @@ -69,7 +69,7 @@ return true; } - @Specialization(guards = "guard ()") + @Specialization(guards = "guard()") int do1() { return 42; } @@ -214,7 +214,7 @@ return true; } - @ExpectError("No compatible guard with method name 'guard(' found.%") + @ExpectError("Error parsing expression 'guard(': -- line 1 col 7: \")\" expected%") @Specialization(guards = "guard(") int do1() { return 42; @@ -227,7 +227,7 @@ return true; } - @ExpectError("No compatible guard with method name 'guard)' found.%") + @ExpectError("Error parsing expression 'guard)': -- line 1 col 6: EOF expected%") @Specialization(guards = "guard)") int do1() { return 42; @@ -241,7 +241,7 @@ return true; } - @ExpectError("Guard parameter 'a' for guard 'guard' could not be mapped to a declared child node.") + @ExpectError("Error parsing expression 'guard(a)': a cannot be resolved.") @Specialization(guards = "guard(a)") int do1() { return 42; @@ -255,7 +255,7 @@ return true; } - @ExpectError("Guard parameter 'a' for guard 'guard' could not be mapped to a declared child node.") + @ExpectError("Error parsing expression 'guard(a)': a cannot be resolved.") @Specialization(guards = "guard(a)") int do1(int b) { return b; diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java Fri Jan 23 02:55:23 2015 +0100 @@ -45,7 +45,7 @@ return true; } - @Specialization(guards = "!guard") + @Specialization(guards = "!guard()") int do1() { throw new AssertionError(); } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java Fri Jan 23 02:55:23 2015 +0100 @@ -182,7 +182,7 @@ return false; } - @Specialization(guards = "foo") + @Specialization(guards = "foo()") int do2() { return 1; } @@ -206,7 +206,7 @@ } @ExpectError("Specialization is not reachable. It is shadowed by do2().") - @Specialization(guards = "foo") + @Specialization(guards = "foo()") int do1() { return 1; } @@ -219,7 +219,7 @@ return false; } - @Specialization(guards = "foo") + @Specialization(guards = "foo()") int do2() { return 1; } @@ -237,13 +237,13 @@ return false; } - @Specialization(guards = "foo") + @Specialization(guards = "foo()") int do2() { return 1; } @ExpectError("Specialization is not reachable. It is shadowed by do2().") - @Specialization(guards = "foo") + @Specialization(guards = "foo()") int do1() { return 2; } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java Fri Jan 23 02:55:23 2015 +0100 @@ -119,7 +119,7 @@ return false; } - @Specialization(guards = "guard") + @Specialization(guards = "guard(a, hasB, b)") int doIt(int a, boolean hasB, int b) { return a + b; } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java Fri Jan 23 02:55:23 2015 +0100 @@ -74,29 +74,17 @@ @NodeChild("a") static class SourceSection0 extends ValueNode { - boolean isOne(int a) { - return a == 1; - } - - boolean isTwo(int a) { - return a == 2; - } - - boolean isThree(int a) { - return a == 3; - } - - @Specialization(guards = "isOne") + @Specialization(guards = "a == 1") int do1(int a) { return a; } - @Specialization(guards = "isTwo") + @Specialization(guards = "a == 2") int do2(int a) { return a; } - @Specialization(guards = "isThree") + @Specialization(guards = "a == 3") int do3(int a) { return a; } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java Fri Jan 23 02:55:23 2015 +0100 @@ -212,7 +212,7 @@ return a == 1; } - @Specialization(guards = "guard0") + @Specialization(guards = "guard0(a)") int do2(int a) { return a; } @@ -309,7 +309,7 @@ static int fallthrough1; - @Specialization(guards = "isDo1", rewriteOn = ArithmeticException.class) + @Specialization(guards = "isDo1(a)", rewriteOn = ArithmeticException.class) int do1(int a) throws ArithmeticException { if (a == 0) { fallthrough1++; @@ -322,7 +322,7 @@ return a == 0 || a == 1; } - @Specialization(guards = "isDo1") + @Specialization(guards = "isDo1(a)") int do2(int a) { return a; } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java Fri Jan 23 02:55:23 2015 +0100 @@ -58,9 +58,9 @@ TestGrouping.true3 = 0; Assert.assertEquals(42, TestHelper.executeWith(root, 21, 21)); - Assert.assertEquals(4, TestGrouping.true1); + Assert.assertEquals(5, TestGrouping.true1); Assert.assertEquals(0, TestGrouping.false1); - Assert.assertEquals(4, TestGrouping.true2); + Assert.assertEquals(5, TestGrouping.true2); Assert.assertEquals(5, TestGrouping.false2); Assert.assertEquals(5, TestGrouping.true3); Assert.assertEquals(10, SimpleTypes.intCheck); @@ -69,9 +69,9 @@ Assert.assertEquals(4, a3.checked); Assert.assertEquals(42, TestHelper.executeWith(root, 21, 21)); - Assert.assertEquals(5, TestGrouping.true1); + Assert.assertEquals(6, TestGrouping.true1); Assert.assertEquals(0, TestGrouping.false1); - Assert.assertEquals(5, TestGrouping.true2); + Assert.assertEquals(6, TestGrouping.true2); Assert.assertEquals(6, TestGrouping.false2); Assert.assertEquals(6, TestGrouping.true3); @@ -123,32 +123,32 @@ throw new AssertionError(); } - @Specialization(guards = {"true1", "true2", "!false2", "true3"}, assumptions = {"a1", "a3"}, rewriteOn = RuntimeException.class) + @Specialization(guards = {"true1(value1)", "true2(value1)", "!false2(value1)", "true3(value1)"}, assumptions = {"a1", "a3"}, rewriteOn = RuntimeException.class) public int throwRewrite(int value1, int value2) { throw new RuntimeException(); } - @Specialization(guards = {"true1", "true2", "!false2", "true3"}, contains = "throwRewrite", assumptions = {"a1", "a3"}) + @Specialization(guards = {"true1(value1)", "true2(value1)", "!false2(value1)", "true3(value1)"}, contains = "throwRewrite", assumptions = {"a1", "a3"}) public int success(int value1, int value2) { return value1 + value2; } - @Specialization(guards = {"true1", "true2", "!false2", "!true3"}, assumptions = {"a1", "a3"}) + @Specialization(guards = {"true1(value1)", "true2(value1)", "!false2(value1)", "!true3(value1)"}, assumptions = {"a1", "a3"}) public int fail5(int value1, int value2) { throw new AssertionError(); } - @Specialization(guards = {"true1", "true2", "false2"}, assumptions = {"a1", "a3"}) + @Specialization(guards = {"true1(value1)", "true2(value1)", "false2(value1)"}, assumptions = {"a1", "a3"}) public int fail4(int value1, int value2) { throw new AssertionError(); } - @Specialization(guards = {"true1", "true2"}, assumptions = {"a1", "a3"}) + @Specialization(guards = {"true1(value1)", "true2(value1)"}, assumptions = {"a1", "a3"}) public int fail2break(int value1, int value2) { throw new AssertionError(); } - @Specialization(guards = {"true1", "false1"}) + @Specialization(guards = {"true1(value1)", "false1(value1, value2)"}) public int fail1(int value1, int value2) { throw new AssertionError(); } @@ -165,17 +165,17 @@ @NodeChild(value = "genericChild", type = GenericInt.class) public abstract static class TestElseConnectionBug1 extends ValueNode { - @Specialization(rewriteOn = {SlowPathException.class}, guards = "isInitialized") + @Specialization(rewriteOn = {SlowPathException.class}, guards = "isInitialized(value)") public int do1(int value) throws SlowPathException { throw new SlowPathException(); } - @Specialization(contains = "do1", guards = "isInitialized") + @Specialization(contains = "do1", guards = "isInitialized(value)") public int do2(int value) { return value == 42 ? value : 0; } - @Specialization(guards = "!isInitialized") + @Specialization(guards = "!isInitialized(value)") public Object do3(int value) { throw new AssertionError(); } @@ -208,17 +208,17 @@ @NodeChild public abstract static class TestElseConnectionBug2 extends ValueNode { - @Specialization(guards = "guard0") + @Specialization(guards = "guard0(value)") public int do1(int value) { throw new AssertionError(); } - @Specialization(guards = "guard1") + @Specialization(guards = "guard1(value)") public int do2(int value) { throw new AssertionError(); } - @Specialization(guards = "!guard0") + @Specialization(guards = "!guard0(value)") public int do3(int value) { return value; } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Copyright.frame --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Copyright.frame Fri Jan 23 02:55:23 2015 +0100 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2015, 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. + */ + +// The content of this file is automatically generated. DO NOT EDIT. diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpression.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpression.java Fri Jan 23 02:55:23 2015 +0100 @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2015, 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.expression; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public abstract class DSLExpression { + + private DSLExpression() { + } + + public static DSLExpression parse(String input) { + return Parser.parse(input); + } + + public final List findBoundVariables() { + final List variables = new ArrayList<>(); + this.accept(new AbstractDSLExpressionVisitor() { + + @Override + public void visitVariable(Variable variable) { + if (variable.getReceiver() == null) { + variables.add(variable); + } + } + + }); + return variables; + } + + public final boolean isVariableBound(VariableElement variableElement) { + for (Variable variable : findBoundVariables()) { + if (variable.getResolvedVariable() == variableElement) { + return true; + } + } + return false; + } + + public abstract TypeMirror getResolvedType(); + + public abstract void accept(DSLExpressionVisitor visitor); + + public static final class Negate extends DSLExpression { + + private final DSLExpression receiver; + + public Negate(DSLExpression receiver) { + this.receiver = receiver; + } + + @Override + public void accept(DSLExpressionVisitor visitor) { + receiver.accept(visitor); + visitor.visitNegate(this); + } + + public DSLExpression getReceiver() { + return receiver; + } + + @Override + public TypeMirror getResolvedType() { + return receiver.getResolvedType(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Negate) { + return receiver.equals(((Negate) obj).receiver); + } + return false; + } + + @Override + public int hashCode() { + return receiver.hashCode(); + } + } + + public static final class Binary extends DSLExpression { + + private final String operator; + private final DSLExpression left; + private final DSLExpression right; + + private TypeMirror resolvedType; + + public Binary(String operator, DSLExpression left, DSLExpression right) { + this.operator = operator; + this.left = left; + this.right = right; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Binary) { + Binary other = (Binary) obj; + return operator.equals(other.operator) && left.equals(other.left) && right.equals(other.right); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(operator, left, right); + } + + public String getOperator() { + return operator; + } + + public DSLExpression getLeft() { + return left; + } + + public DSLExpression getRight() { + return right; + } + + @Override + public void accept(DSLExpressionVisitor visitor) { + left.accept(visitor); + right.accept(visitor); + visitor.visitBinary(this); + } + + @Override + public TypeMirror getResolvedType() { + return resolvedType; + } + + public void setResolvedType(TypeMirror resolvedType) { + this.resolvedType = resolvedType; + } + + @Override + public String toString() { + return "Binary [left=" + left + ", operator=" + operator + ", right=" + right + ", resolvedType=" + resolvedType + "]"; + } + + } + + public static final class Call extends DSLExpression { + + private final DSLExpression receiver; + private final String name; + private final List parameters; + + private ExecutableElement resolvedMethod; + + public Call(DSLExpression receiver, String name, List parameters) { + this.receiver = receiver; + this.name = name; + this.parameters = parameters; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Call) { + Call other = (Call) obj; + return Objects.equals(receiver, other.receiver) && name.equals(other.name) && parameters.equals(other.parameters); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(receiver, name, parameters); + } + + public DSLExpression getReceiver() { + return receiver; + } + + public String getName() { + return name; + } + + public List getParameters() { + return parameters; + } + + @Override + public void accept(DSLExpressionVisitor visitor) { + if (receiver != null) { + receiver.accept(visitor); + } + for (DSLExpression parameter : getParameters()) { + parameter.accept(visitor); + } + visitor.visitCall(this); + } + + @Override + public TypeMirror getResolvedType() { + return resolvedMethod != null ? resolvedMethod.getReturnType() : null; + } + + public ExecutableElement getResolvedMethod() { + return resolvedMethod; + } + + public void setResolvedMethod(ExecutableElement resolvedMethod) { + this.resolvedMethod = resolvedMethod; + } + + @Override + public String toString() { + return "Call [receiver=" + receiver + ", name=" + name + ", parameters=" + parameters + ", resolvedMethod=" + resolvedMethod + "]"; + } + + } + + public static final class Variable extends DSLExpression { + + private final DSLExpression receiver; + private final String name; + + private VariableElement resolvedVariable; + + public Variable(DSLExpression receiver, String name) { + this.receiver = receiver; + this.name = name; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Variable) { + Variable other = (Variable) obj; + return Objects.equals(receiver, other.receiver) && name.equals(other.name); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(receiver, name); + } + + public DSLExpression getReceiver() { + return receiver; + } + + public String getName() { + return name; + } + + @Override + public void accept(DSLExpressionVisitor visitor) { + if (receiver != null) { + receiver.accept(visitor); + } + visitor.visitVariable(this); + } + + @Override + public TypeMirror getResolvedType() { + return resolvedVariable != null ? resolvedVariable.asType() : null; + } + + public void setResolvedVariable(VariableElement resolvedVariable) { + this.resolvedVariable = resolvedVariable; + } + + public VariableElement getResolvedVariable() { + return resolvedVariable; + } + + @Override + public String toString() { + return "Variable [receiver=" + receiver + ", name=" + name + ", resolvedVariable=" + resolvedVariable + "]"; + } + + } + + public static final class IntLiteral extends DSLExpression { + + private final String literal; + + private int resolvedValueInt; + private TypeMirror resolvedType; + + public IntLiteral(String literal) { + this.literal = literal; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof IntLiteral) { + IntLiteral other = (IntLiteral) obj; + return resolvedValueInt == other.resolvedValueInt; + } + return false; + } + + @Override + public int hashCode() { + return resolvedValueInt; + } + + public String getLiteral() { + return literal; + } + + public int getResolvedValueInt() { + return resolvedValueInt; + } + + public void setResolvedValueInt(int resolved) { + this.resolvedValueInt = resolved; + } + + @Override + public TypeMirror getResolvedType() { + return resolvedType; + } + + public void setResolvedType(TypeMirror resolvedType) { + this.resolvedType = resolvedType; + } + + @Override + public void accept(DSLExpressionVisitor visitor) { + visitor.visitIntLiteral(this); + } + + @Override + public String toString() { + return "IntLiteral [literal=" + literal + ", resolvedValueInt=" + resolvedValueInt + ", resolvedType=" + resolvedType + "]"; + } + + } + + public abstract class AbstractDSLExpressionVisitor implements DSLExpressionVisitor { + + public void visitBinary(Binary binary) { + } + + public void visitCall(Call binary) { + } + + public void visitIntLiteral(IntLiteral binary) { + } + + public void visitNegate(Negate negate) { + } + + public void visitVariable(Variable binary) { + } + } + + public interface DSLExpressionVisitor { + + void visitBinary(Binary binary); + + void visitNegate(Negate negate); + + void visitCall(Call binary); + + void visitVariable(Variable binary); + + void visitIntLiteral(IntLiteral binary); + + } + +} diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java Fri Jan 23 02:55:23 2015 +0100 @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2015, 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.expression; + +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.expression.DSLExpression.Binary; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Call; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.DSLExpressionVisitor; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.IntLiteral; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.java.model.*; + +public class DSLExpressionResolver implements DSLExpressionVisitor { + + private static final List LOGIC_OPERATORS = Arrays.asList("||"); + private static final List COMPARABLE_OPERATORS = Arrays.asList("<", "<=", ">", ">="); + private static final List IDENTITY_OPERATORS = Arrays.asList("==", "!="); + private static final String CONSTRUCTOR_KEYWORD = "new"; + + private List variables; + private List methods; + private final ProcessorContext context; + + public DSLExpressionResolver(ProcessorContext context, List lookupElements) { + this.context = context; + this.variables = variablesIn(lookupElements, false); + this.methods = methodsIn(lookupElements); + } + + private static List methodsIn(List lookupElements) { + List methods = new ArrayList<>(); + for (Element variable : lookupElements) { + ElementKind kind = variable.getKind(); + if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) { + methods.add((ExecutableElement) variable); + } + } + return methods; + } + + private static List variablesIn(List lookupElements, boolean publicOnly) { + List variables = new ArrayList<>(); + for (Element variable : lookupElements) { + ElementKind kind = variable.getKind(); + if (kind == ElementKind.LOCAL_VARIABLE || kind == ElementKind.PARAMETER || kind == ElementKind.FIELD || kind == ElementKind.ENUM_CONSTANT) { + VariableElement variableElement = (VariableElement) variable; + if (!publicOnly || variableElement.getModifiers().contains(Modifier.PUBLIC)) { + variables.add(variableElement); + } + } + } + return variables; + } + + private static String getMethodName(ExecutableElement method) { + if (method.getKind() == ElementKind.CONSTRUCTOR) { + return CONSTRUCTOR_KEYWORD; + } else { + return method.getSimpleName().toString(); + } + } + + public void visitBinary(Binary binary) { + String operator = binary.getOperator(); + TypeMirror leftType = binary.getLeft().getResolvedType(); + TypeMirror rightType = binary.getRight().getResolvedType(); + if (!ElementUtils.typeEquals(leftType, rightType)) { + throw new InvalidExpressionException(String.format("Incompatible operand types %s and %s.", ElementUtils.getSimpleName(leftType), ElementUtils.getSimpleName(rightType))); + } + + TypeMirror booleanType = context.getType(boolean.class); + boolean valid; + if (LOGIC_OPERATORS.contains(operator)) { + valid = ElementUtils.typeEquals(leftType, booleanType); + } else if (COMPARABLE_OPERATORS.contains(operator)) { + valid = ElementUtils.isPrimitive(leftType); + } else if (IDENTITY_OPERATORS.contains(operator)) { + valid = leftType.getKind().isPrimitive() || leftType.getKind() == TypeKind.DECLARED || leftType.getKind() == TypeKind.ARRAY; + } else { + throw new InvalidExpressionException(String.format("The operator %s is undefined.", operator)); + } + binary.setResolvedType(booleanType); + + if (!valid) { + throw new InvalidExpressionException(String.format("The operator %s is undefined for the argument type(s) %s %s.", operator, ElementUtils.getSimpleName(leftType), + ElementUtils.getSimpleName(rightType))); + } + } + + public void visitNegate(Negate negate) { + TypeMirror booleanType = context.getType(boolean.class); + TypeMirror resolvedType = negate.getResolvedType(); + if (!ElementUtils.typeEquals(resolvedType, booleanType)) { + throw new InvalidExpressionException(String.format("The operator %s is undefined for the argument type %s.", "!", ElementUtils.getSimpleName(resolvedType))); + } + } + + public void visitCall(Call call) { + List lookupMethods; + DSLExpression receiver = call.getReceiver(); + if (receiver == null) { + lookupMethods = this.methods; + } else { + TypeMirror type = receiver.getResolvedType(); + if (type.getKind() == TypeKind.DECLARED) { + type = context.reloadType(type); // ensure ECJ has the type loaded + lookupMethods = ElementFilter.methodsIn(context.getEnvironment().getElementUtils().getAllMembers((TypeElement) ((DeclaredType) type).asElement())); + } else { + lookupMethods = Collections.emptyList(); + } + } + + ExecutableElement foundWithName = null; + outer: for (ExecutableElement method : lookupMethods) { + if (getMethodName(method).equals(call.getName())) { + foundWithName = method; + + List parameters = method.getParameters(); + if (parameters.size() != call.getParameters().size()) { + continue outer; + } + + int parameterIndex = 0; + for (DSLExpression expression : call.getParameters()) { + TypeMirror sourceType = expression.getResolvedType(); + TypeMirror targetType = parameters.get(parameterIndex).asType(); + if (!ElementUtils.isAssignable(sourceType, targetType)) { + continue outer; + } + parameterIndex++; + } + call.setResolvedMethod(method); + break; + } + } + if (call.getResolvedMethod() == null) { + if (foundWithName == null) { + // parameter mismatch + throw new InvalidExpressionException(String.format("The method %s is undefined for the enclosing scope.", call.getName())); + } else { + StringBuilder arguments = new StringBuilder(); + String sep = ""; + for (DSLExpression expression : call.getParameters()) { + arguments.append(sep).append(ElementUtils.getSimpleName(expression.getResolvedType())); + sep = ", "; + } + // name mismatch + throw new InvalidExpressionException(String.format("The method %s in the type %s is not applicable for the arguments %s.", // + ElementUtils.getReadableSignature(foundWithName), // + ElementUtils.getSimpleName((TypeElement) foundWithName.getEnclosingElement()), arguments.toString())); + } + } + } + + public void visitVariable(Variable variable) { + List lookupVariables; + DSLExpression receiver = variable.getReceiver(); + if (receiver == null) { + lookupVariables = this.variables; + } else { + TypeMirror type = receiver.getResolvedType(); + if (type.getKind() == TypeKind.DECLARED) { + type = context.reloadType(type); // ensure ECJ has the type loaded + lookupVariables = variablesIn(context.getEnvironment().getElementUtils().getAllMembers((TypeElement) ((DeclaredType) type).asElement()), true); + } else if (type.getKind() == TypeKind.ARRAY) { + lookupVariables = Arrays. asList(new CodeVariableElement(context.getType(int.class), "length")); + } else { + lookupVariables = Collections.emptyList(); + } + } + + for (VariableElement variableElement : lookupVariables) { + if (variableElement.getSimpleName().toString().equals(variable.getName())) { + variable.setResolvedVariable(variableElement); + break; + } + } + if (variable.getResolvedVariable() == null) { + throw new InvalidExpressionException(String.format("%s cannot be resolved.", variable.getName())); + } + } + + public void visitIntLiteral(IntLiteral binary) { + try { + binary.setResolvedType(context.getType(int.class)); + binary.setResolvedValueInt(Integer.parseInt(binary.getLiteral())); + } catch (NumberFormatException e) { + throw new InvalidExpressionException(String.format("Type mismatch: cannot convert from String '%s' to int", binary.getLiteral())); + } + } + +} diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Expression.atg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Expression.atg Fri Jan 23 02:55:23 2015 +0100 @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2015, 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 is the grammar for DSL expressions that is used to automatically generate the Parser.java and Scanner.java + * files. You can download the parser generator Coco/R from http://ssw.jku.at/coco/. Then run + * "java -jar Coco.jar Expression.atg" + */ + +COMPILER Expression + +CHARACTERS + +letter = 'A'..'Z' + 'a'..'z'. +nonZeroDigit = "123456789". +digit = "0123456789". + +TOKENS + +identifier = letter {letter | digit}. +numericLiteral = "0" | nonZeroDigit { digit }. + +PRAGMAS + +PRODUCTIONS + + +Expression += +NegateFactor +. + +NegateFactor += (. boolean negated = false; .) +[ + "!" (. negated = true; .) +] + LogicFactor (. result = negated ? new Negate(result) : result;.) +. + + +LogicFactor += +Factor +[ + ("<" | "<=" | ">" | ">=" | "==" | "!=" ) (. Token op = t; .) + Factor (. result = new Binary(op.val, result, right); .) +] +. + + +Factor += (. result = null; .) + +( + MemberExpression +| + numericLiteral (. result = new IntLiteral(t.val); .) +| + "(" + Expression + ")" + +) +. + +MemberExpression += (. result = null; .) +( + + identifier (. Variable variable = new Variable(receiver, t.val); .) + (. result = variable; .) +[ + + "(" (. List parameters = new ArrayList<>(); + DSLExpression parameter; .) + [ + Expression (. parameters.add(parameter); .) + { + "," + Expression (. parameters.add(parameter); .) + } + ] + ")" (. result = new Call(variable.getReceiver(), variable.getName(), parameters); .) +] + +) +[ + "." MemberExpression +] +. +END Expression. + + + diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/InvalidExpressionException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/InvalidExpressionException.java Fri Jan 23 02:55:23 2015 +0100 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015, 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.expression; + +public class InvalidExpressionException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public InvalidExpressionException(String message) { + super(message); + } +} diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.frame --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.frame Fri Jan 23 02:55:23 2015 +0100 @@ -0,0 +1,211 @@ +/*------------------------------------------------------------------------- +Compiler Generator Coco/R, +Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz +extended by M. Loeberbauer & A. Woess, Univ. of Linz +ported from C# to Java by Wolfgang Ahorner +with improvements by Pat Terry, Rhodes University + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program 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 +for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +As an exception, it is allowed to write an extension of Coco/R that is +used as a plugin in non-free software. + +If not otherwise stated, any source code generated by Coco/R (other than +Coco/R itself) does not fall under the GNU General Public License. +------------------------------------------------------------------------*/ +-->begin +package com.oracle.truffle.dsl.processor.expression; + +import java.util.*; +import java.io.*; +import java.nio.charset.*; + +import com.oracle.truffle.dsl.processor.expression.DSLExpression.*; + +// Checkstyle: stop +// @formatter:off +class Parser { +-->constants + static final boolean _T = true; + static final boolean _x = false; + static final int minErrDist = 2; + + public Token t; // last recognized token + public Token la; // lookahead token + int errDist = minErrDist; + + public final Scanner scanner; + public final Errors errors; + + -->declarations + public Parser(InputStream input) { + this.scanner = new Scanner(input); + errors = new Errors(); + } + + void SynErr(int n) { + if (errDist >= minErrDist) + errors.SynErr(la.line, la.col, n); + errDist = 0; + } + + public void SemErr(String msg) { + if (errDist >= minErrDist) + errors.SemErr(t.line, t.col, msg); + errDist = 0; + } + + void Get() { + for (;;) { + t = la; + la = scanner.Scan(); + if (la.kind <= maxT) { + ++errDist; + break; + } +-->pragmas + la = t; + } + } + + void Expect(int n) { + if (la.kind == n) + Get(); + else { + SynErr(n); + } + } + + boolean StartOf(int s) { + return set[s][la.kind]; + } + + void ExpectWeak(int n, int follow) { + if (la.kind == n) + Get(); + else { + SynErr(n); + while (!StartOf(follow)) + Get(); + } + } + + boolean WeakSeparator(int n, int syFol, int repFol) { + int kind = la.kind; + if (kind == n) { + Get(); + return true; + } else if (StartOf(repFol)) + return false; + else { + SynErr(n); + while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) { + Get(); + kind = la.kind; + } + return StartOf(syFol); + } + } + +-->productions + + private DSLExpression parseImpl() { + la = new Token(); + la.val = ""; + Get(); + DSLExpression result = -->parseRoot + return result; + } + + private static final boolean[][] set = { +-->initialization + }; + + public static DSLExpression parse(InputStream input) { + Parser parser = new Parser(input); + DSLExpression result = parser.parseImpl(); + if (parser.errors.errors.size() > 0) { + StringBuilder msg = new StringBuilder(); + for (String error : parser.errors.errors) { + msg.append(error).append("\n"); + } + throw new InvalidExpressionException(msg.toString()); + } + return result; + } + + public static DSLExpression parse(String s) { + return parse(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8))); + } +} // end Parser + +class Errors { + + protected final List errors = new ArrayList<>(); + public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text + + protected void printMsg(int line, int column, String msg) { + StringBuffer b = new StringBuffer(errMsgFormat); + int pos = b.indexOf("{0}"); + if (pos >= 0) { + b.delete(pos, pos + 3); + b.insert(pos, line); + } + pos = b.indexOf("{1}"); + if (pos >= 0) { + b.delete(pos, pos + 3); + b.insert(pos, column); + } + pos = b.indexOf("{2}"); + if (pos >= 0) + b.replace(pos, pos + 3, msg); + errors.add(b.toString()); + } + + public void SynErr(int line, int col, int n) { + String s; + switch (n) {-->errors + default: + s = "error " + n; + break; + } + printMsg(line, col, s); + } + + public void SemErr(int line, int col, String s) { + printMsg(line, col, s); + } + + public void SemErr(String s) { + errors.add(s); + } + + public void Warning(int line, int col, String s) { + printMsg(line, col, s); + } + + public void Warning(String s) { + errors.add(s); + } +} // Errors + +class FatalError extends RuntimeException { + + public static final long serialVersionUID = 1L; + + public FatalError(String s) { + super(s); + } +} diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.java Fri Jan 23 02:55:23 2015 +0100 @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2015, 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. + */ + +// The content of this file is automatically generated. DO NOT EDIT. + +package com.oracle.truffle.dsl.processor.expression; + +import java.util.*; +import java.io.*; +import java.nio.charset.*; + +import com.oracle.truffle.dsl.processor.expression.DSLExpression.*; + +// Checkstyle: stop +// @formatter:off +class Parser { + public static final int _EOF = 0; + public static final int _identifier = 1; + public static final int _numericLiteral = 2; + public static final int maxT = 14; + + static final boolean _T = true; + static final boolean _x = false; + static final int minErrDist = 2; + + public Token t; // last recognized token + public Token la; // lookahead token + int errDist = minErrDist; + + public final Scanner scanner; + public final Errors errors; + + + public Parser(InputStream input) { + this.scanner = new Scanner(input); + errors = new Errors(); + } + + void SynErr(int n) { + if (errDist >= minErrDist) + errors.SynErr(la.line, la.col, n); + errDist = 0; + } + + public void SemErr(String msg) { + if (errDist >= minErrDist) + errors.SemErr(t.line, t.col, msg); + errDist = 0; + } + + void Get() { + for (;;) { + t = la; + la = scanner.Scan(); + if (la.kind <= maxT) { + ++errDist; + break; + } + + la = t; + } + } + + void Expect(int n) { + if (la.kind == n) + Get(); + else { + SynErr(n); + } + } + + boolean StartOf(int s) { + return set[s][la.kind]; + } + + void ExpectWeak(int n, int follow) { + if (la.kind == n) + Get(); + else { + SynErr(n); + while (!StartOf(follow)) + Get(); + } + } + + boolean WeakSeparator(int n, int syFol, int repFol) { + int kind = la.kind; + if (kind == n) { + Get(); + return true; + } else if (StartOf(repFol)) + return false; + else { + SynErr(n); + while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) { + Get(); + kind = la.kind; + } + return StartOf(syFol); + } + } + + DSLExpression Expression() { + DSLExpression result; + result = NegateFactor(); + return result; + } + + DSLExpression NegateFactor() { + DSLExpression result; + boolean negated = false; + if (la.kind == 3) { + Get(); + negated = true; + } + result = LogicFactor(); + result = negated ? new Negate(result) : result; + return result; + } + + DSLExpression LogicFactor() { + DSLExpression result; + result = Factor(); + if (StartOf(1)) { + switch (la.kind) { + case 4: { + Get(); + break; + } + case 5: { + Get(); + break; + } + case 6: { + Get(); + break; + } + case 7: { + Get(); + break; + } + case 8: { + Get(); + break; + } + case 9: { + Get(); + break; + } + } + Token op = t; + DSLExpression right = Factor(); + result = new Binary(op.val, result, right); + } + return result; + } + + DSLExpression Factor() { + DSLExpression result; + result = null; + if (la.kind == 1) { + result = MemberExpression(result); + } else if (la.kind == 2) { + Get(); + result = new IntLiteral(t.val); + } else if (la.kind == 10) { + Get(); + result = Expression(); + Expect(11); + } else SynErr(15); + return result; + } + + DSLExpression MemberExpression(DSLExpression receiver) { + DSLExpression result; + result = null; + Expect(1); + Variable variable = new Variable(receiver, t.val); + result = variable; + if (la.kind == 10) { + Get(); + List parameters = new ArrayList<>(); + DSLExpression parameter; + if (StartOf(2)) { + parameter = Expression(); + parameters.add(parameter); + while (la.kind == 12) { + Get(); + parameter = Expression(); + parameters.add(parameter); + } + } + Expect(11); + result = new Call(variable.getReceiver(), variable.getName(), parameters); + } + if (la.kind == 13) { + Get(); + result = MemberExpression(result); + } + return result; + } + + + + private DSLExpression parseImpl() { + la = new Token(); + la.val = ""; + Get(); + DSLExpression result = Expression(); + Expect(0); + + return result; + } + + private static final boolean[][] set = { + {_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x}, + {_x,_x,_x,_x, _T,_T,_T,_T, _T,_T,_x,_x, _x,_x,_x,_x}, + {_x,_T,_T,_T, _x,_x,_x,_x, _x,_x,_T,_x, _x,_x,_x,_x} + + }; + + public static DSLExpression parse(InputStream input) { + Parser parser = new Parser(input); + DSLExpression result = parser.parseImpl(); + if (parser.errors.errors.size() > 0) { + StringBuilder msg = new StringBuilder(); + for (String error : parser.errors.errors) { + msg.append(error).append("\n"); + } + throw new InvalidExpressionException(msg.toString()); + } + return result; + } + + public static DSLExpression parse(String s) { + return parse(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8))); + } +} // end Parser + +class Errors { + + protected final List errors = new ArrayList<>(); + public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text + + protected void printMsg(int line, int column, String msg) { + StringBuffer b = new StringBuffer(errMsgFormat); + int pos = b.indexOf("{0}"); + if (pos >= 0) { + b.delete(pos, pos + 3); + b.insert(pos, line); + } + pos = b.indexOf("{1}"); + if (pos >= 0) { + b.delete(pos, pos + 3); + b.insert(pos, column); + } + pos = b.indexOf("{2}"); + if (pos >= 0) + b.replace(pos, pos + 3, msg); + errors.add(b.toString()); + } + + public void SynErr(int line, int col, int n) { + String s; + switch (n) { + case 0: s = "EOF expected"; break; + case 1: s = "identifier expected"; break; + case 2: s = "numericLiteral expected"; break; + case 3: s = "\"!\" expected"; break; + case 4: s = "\"<\" expected"; break; + case 5: s = "\"<=\" expected"; break; + case 6: s = "\">\" expected"; break; + case 7: s = "\">=\" expected"; break; + case 8: s = "\"==\" expected"; break; + case 9: s = "\"!=\" expected"; break; + case 10: s = "\"(\" expected"; break; + case 11: s = "\")\" expected"; break; + case 12: s = "\",\" expected"; break; + case 13: s = "\".\" expected"; break; + case 14: s = "??? expected"; break; + case 15: s = "invalid Factor"; break; + default: + s = "error " + n; + break; + } + printMsg(line, col, s); + } + + public void SemErr(int line, int col, String s) { + printMsg(line, col, s); + } + + public void SemErr(String s) { + errors.add(s); + } + + public void Warning(int line, int col, String s) { + printMsg(line, col, s); + } + + public void Warning(String s) { + errors.add(s); + } +} // Errors + +class FatalError extends RuntimeException { + + public static final long serialVersionUID = 1L; + + public FatalError(String s) { + super(s); + } +} diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.frame --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.frame Fri Jan 23 02:55:23 2015 +0100 @@ -0,0 +1,495 @@ +/*------------------------------------------------------------------------- +Compiler Generator Coco/R, +Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz +extended by M. Loeberbauer & A. Woess, Univ. of Linz +ported from C# to Java by Wolfgang Ahorner +with improvements by Pat Terry, Rhodes University + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program 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 +for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +As an exception, it is allowed to write an extension of Coco/R that is +used as a plugin in non-free software. + +If not otherwise stated, any source code generated by Coco/R (other than +Coco/R itself) does not fall under the GNU General Public License. +------------------------------------------------------------------------*/ +-->begin +package com.oracle.truffle.dsl.processor.expression; + +import java.io.InputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Map; +import java.util.HashMap; + +// Checkstyle: stop +// @formatter:off +class Token { + + public int kind; // token kind + public int pos; // token position in bytes in the source text (starting at 0) + public int charPos; // token position in characters in the source text (starting at 0) + public int col; // token column (starting at 1) + public int line; // token line (starting at 1) + public String val; // token value + public Token next; // ML 2005-03-11 Peek tokens are kept in linked list +} + +// ----------------------------------------------------------------------------------- +// Buffer +// ----------------------------------------------------------------------------------- +class Buffer { + + // This Buffer supports the following cases: + // 1) seekable stream (file) + // a) whole stream in buffer + // b) part of stream in buffer + // 2) non seekable stream (network, console) + + public static final int EOF = Character.MAX_VALUE + 1; + private static final int MIN_BUFFER_LENGTH = 1024; // 1KB + private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB + private byte[] buf; // input buffer + private int bufStart; // position of first byte in buffer relative to input stream + private int bufLen; // length of buffer + private int fileLen; // length of input stream (may change if stream is no file) + private int bufPos; // current position in buffer + private RandomAccessFile file; // input stream (seekable) + private InputStream stream; // growing input stream (e.g.: console, network) + + public Buffer(InputStream s) { + stream = s; + fileLen = bufLen = bufStart = bufPos = 0; + buf = new byte[MIN_BUFFER_LENGTH]; + } + + public Buffer(String fileName) { + try { + file = new RandomAccessFile(fileName, "r"); + fileLen = (int) file.length(); + bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH); + buf = new byte[bufLen]; + bufStart = Integer.MAX_VALUE; // nothing in buffer so far + if (fileLen > 0) + setPos(0); // setup buffer to position 0 (start) + else + bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid + if (bufLen == fileLen) + Close(); + } catch (IOException e) { + throw new FatalError("Could not open file " + fileName); + } + } + + // don't use b after this call anymore + // called in UTF8Buffer constructor + protected Buffer(Buffer b) { + buf = b.buf; + bufStart = b.bufStart; + bufLen = b.bufLen; + fileLen = b.fileLen; + bufPos = b.bufPos; + file = b.file; + stream = b.stream; + // keep finalize from closing the file + b.file = null; + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + Close(); + } + + protected void Close() { + if (file != null) { + try { + file.close(); + file = null; + } catch (IOException e) { + throw new FatalError(e.getMessage()); + } + } + } + + public int Read() { + if (bufPos < bufLen) { + return buf[bufPos++] & 0xff; // mask out sign bits + } else if (getPos() < fileLen) { + setPos(getPos()); // shift buffer start to pos + return buf[bufPos++] & 0xff; // mask out sign bits + } else if (stream != null && ReadNextStreamChunk() > 0) { + return buf[bufPos++] & 0xff; // mask out sign bits + } else { + return EOF; + } + } + + public int Peek() { + int curPos = getPos(); + int ch = Read(); + setPos(curPos); + return ch; + } + + // beg .. begin, zero-based, inclusive, in byte + // end .. end, zero-based, exclusive, in byte + public String GetString(int beg, int end) { + int len = 0; + char[] buffer = new char[end - beg]; + int oldPos = getPos(); + setPos(beg); + while (getPos() < end) + buffer[len++] = (char) Read(); + setPos(oldPos); + return new String(buffer, 0, len); + } + + public int getPos() { + return bufPos + bufStart; + } + + public void setPos(int value) { + if (value >= fileLen && stream != null) { + // Wanted position is after buffer and the stream + // is not seek-able e.g. network or console, + // thus we have to read the stream manually till + // the wanted position is in sight. + while (value >= fileLen && ReadNextStreamChunk() > 0) { + // nothing to do... + } + } + + if (value < 0 || value > fileLen) { + throw new FatalError("buffer out of bounds access, position: " + value); + } + + if (value >= bufStart && value < bufStart + bufLen) { // already in buffer + bufPos = value - bufStart; + } else if (file != null) { // must be swapped in + try { + file.seek(value); + bufLen = file.read(buf); + bufStart = value; + bufPos = 0; + } catch (IOException e) { + throw new FatalError(e.getMessage()); + } + } else { + // set the position to the end of the file, Pos will return fileLen. + bufPos = fileLen - bufStart; + } + } + + // Read the next chunk of bytes from the stream, increases the buffer + // if needed and updates the fields fileLen and bufLen. + // Returns the number of bytes read. + private int ReadNextStreamChunk() { + int free = buf.length - bufLen; + if (free == 0) { + // in the case of a growing input stream + // we can neither seek in the stream, nor can we + // foresee the maximum length, thus we must adapt + // the buffer size on demand. + byte[] newBuf = new byte[bufLen * 2]; + System.arraycopy(buf, 0, newBuf, 0, bufLen); + buf = newBuf; + free = bufLen; + } + + int read; + try { + read = stream.read(buf, bufLen, free); + } catch (IOException ioex) { + throw new FatalError(ioex.getMessage()); + } + + if (read > 0) { + fileLen = bufLen = (bufLen + read); + return read; + } + // end of stream reached + return 0; + } +} + +// ----------------------------------------------------------------------------------- +// UTF8Buffer +// ----------------------------------------------------------------------------------- +class UTF8Buffer extends Buffer { + + UTF8Buffer(Buffer b) { + super(b); + } + + @Override + public int Read() { + int ch; + do { + ch = super.Read(); + // until we find a utf8 start (0xxxxxxx or 11xxxxxx) + } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF)); + if (ch < 128 || ch == EOF) { + // nothing to do, first 127 chars are the same in ascii and utf8 + // 0xxxxxxx or end of file character + } else if ((ch & 0xF0) == 0xF0) { + // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + int c1 = ch & 0x07; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = super.Read(); + int c3 = ch & 0x3F; + ch = super.Read(); + int c4 = ch & 0x3F; + ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4; + } else if ((ch & 0xE0) == 0xE0) { + // 1110xxxx 10xxxxxx 10xxxxxx + int c1 = ch & 0x0F; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = super.Read(); + int c3 = ch & 0x3F; + ch = (((c1 << 6) | c2) << 6) | c3; + } else if ((ch & 0xC0) == 0xC0) { + // 110xxxxx 10xxxxxx + int c1 = ch & 0x1F; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = (c1 << 6) | c2; + } + return ch; + } +} + +// ----------------------------------------------------------------------------------- +// StartStates -- maps characters to start states of tokens +// ----------------------------------------------------------------------------------- +class StartStates { + + private static class Elem { + + public int key, val; + public Elem next; + + public Elem(int key, int val) { + this.key = key; + this.val = val; + } + } + + private Elem[] tab = new Elem[128]; + + public void set(int key, int val) { + Elem e = new Elem(key, val); + int k = key % 128; + e.next = tab[k]; + tab[k] = e; + } + + public int state(int key) { + Elem e = tab[key % 128]; + while (e != null && e.key != key) + e = e.next; + return e == null ? 0 : e.val; + } +} + +// ----------------------------------------------------------------------------------- +// Scanner +// ----------------------------------------------------------------------------------- +@SuppressWarnings({"rawtypes"}) +public class Scanner { + + static final char EOL = '\n'; + static final int eofSym = 0; +-->declarations + + public Buffer buffer; // scanner buffer + + Token t; // current token + int ch; // current input character + int pos; // byte position of current character + int charPos; // position by unicode characters starting with 0 + int col; // column number of current character + int line; // line number of current character + int oldEols; // EOLs that appeared in a comment; + static final StartStates start; // maps initial token character to start state + static final Map literals; // maps literal strings to literal kinds + + Token tokens; // list of tokens already peeked (first token is a dummy) + Token pt; // current peek token + + char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged + int tlen; // length of current token + + static { + start = new StartStates(); + literals = new HashMap(); +-->initialization + } + + public Scanner(String fileName) { + buffer = new Buffer(fileName); + Init(); + } + + public Scanner(InputStream s) { + buffer = new Buffer(s); + Init(); + } + + void Init() { + pos = -1; + line = 1; + col = 0; + charPos = -1; + oldEols = 0; + NextCh(); + if (ch == 0xEF) { // check optional byte order mark for UTF-8 + NextCh(); + int ch1 = ch; + NextCh(); + int ch2 = ch; + if (ch1 != 0xBB || ch2 != 0xBF) { + throw new FatalError("Illegal byte order mark at start of file"); + } + buffer = new UTF8Buffer(buffer); + col = 0; + charPos = -1; + NextCh(); + } + pt = tokens = new Token(); // first token is a dummy + } + + void NextCh() { + if (oldEols > 0) { + ch = EOL; + oldEols--; + } else { + pos = buffer.getPos(); + // buffer reads unicode chars, if UTF8 has been detected + ch = buffer.Read(); + col++; + charPos++; + // replace isolated '\r' by '\n' in order to make + // eol handling uniform across Windows, Unix and Mac + if (ch == '\r' && buffer.Peek() != '\n') + ch = EOL; + if (ch == EOL) { + line++; + col = 0; + } + } +-->casing + } + + void AddCh() { + if (tlen >= tval.length) { + char[] newBuf = new char[2 * tval.length]; + System.arraycopy(tval, 0, newBuf, 0, tval.length); + tval = newBuf; + } + if (ch != Buffer.EOF) { +-->casing2 + NextCh(); + } + } + +-->comments + + void CheckLiteral() { + String val = t.val; +-->casing3 + Object kind = literals.get(val); + if (kind != null) { + t.kind = ((Integer) kind).intValue(); + } + } + + Token NextToken() { + while (ch == ' ' || +-->scan1 + ) NextCh(); +-->scan2 + int recKind = noSym; + int recEnd = pos; + t = new Token(); + t.pos = pos; + t.col = col; + t.line = line; + t.charPos = charPos; + int state = start.state(ch); + tlen = 0; + AddCh(); + + loop: for (;;) { + switch (state) { + case -1: { + t.kind = eofSym; + break loop; + } // NextCh already done + case 0: { + if (recKind != noSym) { + tlen = recEnd - t.pos; + SetScannerBehindT(); + } + t.kind = recKind; + break loop; + } // NextCh already done +-->scan3 + } + } + t.val = new String(tval, 0, tlen); + return t; + } + + private void SetScannerBehindT() { + buffer.setPos(t.pos); + NextCh(); + line = t.line; + col = t.col; + charPos = t.charPos; + for (int i = 0; i < tlen; i++) + NextCh(); + } + + // get the next token (possibly a token already seen during peeking) + public Token Scan() { + if (tokens.next == null) { + return NextToken(); + } else { + pt = tokens = tokens.next; + return tokens; + } + } + + // get the next token, ignore pragmas + public Token Peek() { + do { + if (pt.next == null) { + pt.next = NextToken(); + } + pt = pt.next; + } while (pt.kind > maxT); // skip pragmas + + return pt; + } + + // make sure that peeking starts at current scan position + public void ResetPeek() { + pt = tokens; + } + +} // end Scanner diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.java Fri Jan 23 02:55:23 2015 +0100 @@ -0,0 +1,549 @@ +/* + * Copyright (c) 2015, 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. + */ + +// The content of this file is automatically generated. DO NOT EDIT. + +package com.oracle.truffle.dsl.processor.expression; + +import java.io.InputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Map; +import java.util.HashMap; + +// Checkstyle: stop +// @formatter:off +class Token { + + public int kind; // token kind + public int pos; // token position in bytes in the source text (starting at 0) + public int charPos; // token position in characters in the source text (starting at 0) + public int col; // token column (starting at 1) + public int line; // token line (starting at 1) + public String val; // token value + public Token next; // ML 2005-03-11 Peek tokens are kept in linked list +} + +// ----------------------------------------------------------------------------------- +// Buffer +// ----------------------------------------------------------------------------------- +class Buffer { + + // This Buffer supports the following cases: + // 1) seekable stream (file) + // a) whole stream in buffer + // b) part of stream in buffer + // 2) non seekable stream (network, console) + + public static final int EOF = Character.MAX_VALUE + 1; + private static final int MIN_BUFFER_LENGTH = 1024; // 1KB + private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB + private byte[] buf; // input buffer + private int bufStart; // position of first byte in buffer relative to input stream + private int bufLen; // length of buffer + private int fileLen; // length of input stream (may change if stream is no file) + private int bufPos; // current position in buffer + private RandomAccessFile file; // input stream (seekable) + private InputStream stream; // growing input stream (e.g.: console, network) + + public Buffer(InputStream s) { + stream = s; + fileLen = bufLen = bufStart = bufPos = 0; + buf = new byte[MIN_BUFFER_LENGTH]; + } + + public Buffer(String fileName) { + try { + file = new RandomAccessFile(fileName, "r"); + fileLen = (int) file.length(); + bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH); + buf = new byte[bufLen]; + bufStart = Integer.MAX_VALUE; // nothing in buffer so far + if (fileLen > 0) + setPos(0); // setup buffer to position 0 (start) + else + bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid + if (bufLen == fileLen) + Close(); + } catch (IOException e) { + throw new FatalError("Could not open file " + fileName); + } + } + + // don't use b after this call anymore + // called in UTF8Buffer constructor + protected Buffer(Buffer b) { + buf = b.buf; + bufStart = b.bufStart; + bufLen = b.bufLen; + fileLen = b.fileLen; + bufPos = b.bufPos; + file = b.file; + stream = b.stream; + // keep finalize from closing the file + b.file = null; + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + Close(); + } + + protected void Close() { + if (file != null) { + try { + file.close(); + file = null; + } catch (IOException e) { + throw new FatalError(e.getMessage()); + } + } + } + + public int Read() { + if (bufPos < bufLen) { + return buf[bufPos++] & 0xff; // mask out sign bits + } else if (getPos() < fileLen) { + setPos(getPos()); // shift buffer start to pos + return buf[bufPos++] & 0xff; // mask out sign bits + } else if (stream != null && ReadNextStreamChunk() > 0) { + return buf[bufPos++] & 0xff; // mask out sign bits + } else { + return EOF; + } + } + + public int Peek() { + int curPos = getPos(); + int ch = Read(); + setPos(curPos); + return ch; + } + + // beg .. begin, zero-based, inclusive, in byte + // end .. end, zero-based, exclusive, in byte + public String GetString(int beg, int end) { + int len = 0; + char[] buffer = new char[end - beg]; + int oldPos = getPos(); + setPos(beg); + while (getPos() < end) + buffer[len++] = (char) Read(); + setPos(oldPos); + return new String(buffer, 0, len); + } + + public int getPos() { + return bufPos + bufStart; + } + + public void setPos(int value) { + if (value >= fileLen && stream != null) { + // Wanted position is after buffer and the stream + // is not seek-able e.g. network or console, + // thus we have to read the stream manually till + // the wanted position is in sight. + while (value >= fileLen && ReadNextStreamChunk() > 0) { + // nothing to do... + } + } + + if (value < 0 || value > fileLen) { + throw new FatalError("buffer out of bounds access, position: " + value); + } + + if (value >= bufStart && value < bufStart + bufLen) { // already in buffer + bufPos = value - bufStart; + } else if (file != null) { // must be swapped in + try { + file.seek(value); + bufLen = file.read(buf); + bufStart = value; + bufPos = 0; + } catch (IOException e) { + throw new FatalError(e.getMessage()); + } + } else { + // set the position to the end of the file, Pos will return fileLen. + bufPos = fileLen - bufStart; + } + } + + // Read the next chunk of bytes from the stream, increases the buffer + // if needed and updates the fields fileLen and bufLen. + // Returns the number of bytes read. + private int ReadNextStreamChunk() { + int free = buf.length - bufLen; + if (free == 0) { + // in the case of a growing input stream + // we can neither seek in the stream, nor can we + // foresee the maximum length, thus we must adapt + // the buffer size on demand. + byte[] newBuf = new byte[bufLen * 2]; + System.arraycopy(buf, 0, newBuf, 0, bufLen); + buf = newBuf; + free = bufLen; + } + + int read; + try { + read = stream.read(buf, bufLen, free); + } catch (IOException ioex) { + throw new FatalError(ioex.getMessage()); + } + + if (read > 0) { + fileLen = bufLen = (bufLen + read); + return read; + } + // end of stream reached + return 0; + } +} + +// ----------------------------------------------------------------------------------- +// UTF8Buffer +// ----------------------------------------------------------------------------------- +class UTF8Buffer extends Buffer { + + UTF8Buffer(Buffer b) { + super(b); + } + + @Override + public int Read() { + int ch; + do { + ch = super.Read(); + // until we find a utf8 start (0xxxxxxx or 11xxxxxx) + } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF)); + if (ch < 128 || ch == EOF) { + // nothing to do, first 127 chars are the same in ascii and utf8 + // 0xxxxxxx or end of file character + } else if ((ch & 0xF0) == 0xF0) { + // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + int c1 = ch & 0x07; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = super.Read(); + int c3 = ch & 0x3F; + ch = super.Read(); + int c4 = ch & 0x3F; + ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4; + } else if ((ch & 0xE0) == 0xE0) { + // 1110xxxx 10xxxxxx 10xxxxxx + int c1 = ch & 0x0F; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = super.Read(); + int c3 = ch & 0x3F; + ch = (((c1 << 6) | c2) << 6) | c3; + } else if ((ch & 0xC0) == 0xC0) { + // 110xxxxx 10xxxxxx + int c1 = ch & 0x1F; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = (c1 << 6) | c2; + } + return ch; + } +} + +// ----------------------------------------------------------------------------------- +// StartStates -- maps characters to start states of tokens +// ----------------------------------------------------------------------------------- +class StartStates { + + private static class Elem { + + public int key, val; + public Elem next; + + public Elem(int key, int val) { + this.key = key; + this.val = val; + } + } + + private Elem[] tab = new Elem[128]; + + public void set(int key, int val) { + Elem e = new Elem(key, val); + int k = key % 128; + e.next = tab[k]; + tab[k] = e; + } + + public int state(int key) { + Elem e = tab[key % 128]; + while (e != null && e.key != key) + e = e.next; + return e == null ? 0 : e.val; + } +} + +// ----------------------------------------------------------------------------------- +// Scanner +// ----------------------------------------------------------------------------------- +@SuppressWarnings({"rawtypes"}) +public class Scanner { + + static final char EOL = '\n'; + static final int eofSym = 0; + static final int maxT = 14; + static final int noSym = 14; + + + public Buffer buffer; // scanner buffer + + Token t; // current token + int ch; // current input character + int pos; // byte position of current character + int charPos; // position by unicode characters starting with 0 + int col; // column number of current character + int line; // line number of current character + int oldEols; // EOLs that appeared in a comment; + static final StartStates start; // maps initial token character to start state + static final Map literals; // maps literal strings to literal kinds + + Token tokens; // list of tokens already peeked (first token is a dummy) + Token pt; // current peek token + + char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged + int tlen; // length of current token + + static { + start = new StartStates(); + literals = new HashMap(); + for (int i = 65; i <= 90; ++i) start.set(i, 1); + for (int i = 97; i <= 122; ++i) start.set(i, 1); + for (int i = 49; i <= 57; ++i) start.set(i, 2); + start.set(48, 3); + start.set(33, 13); + start.set(60, 14); + start.set(62, 15); + start.set(61, 6); + start.set(40, 9); + start.set(41, 10); + start.set(44, 11); + start.set(46, 12); + start.set(Buffer.EOF, -1); + + } + + public Scanner(String fileName) { + buffer = new Buffer(fileName); + Init(); + } + + public Scanner(InputStream s) { + buffer = new Buffer(s); + Init(); + } + + void Init() { + pos = -1; + line = 1; + col = 0; + charPos = -1; + oldEols = 0; + NextCh(); + if (ch == 0xEF) { // check optional byte order mark for UTF-8 + NextCh(); + int ch1 = ch; + NextCh(); + int ch2 = ch; + if (ch1 != 0xBB || ch2 != 0xBF) { + throw new FatalError("Illegal byte order mark at start of file"); + } + buffer = new UTF8Buffer(buffer); + col = 0; + charPos = -1; + NextCh(); + } + pt = tokens = new Token(); // first token is a dummy + } + + void NextCh() { + if (oldEols > 0) { + ch = EOL; + oldEols--; + } else { + pos = buffer.getPos(); + // buffer reads unicode chars, if UTF8 has been detected + ch = buffer.Read(); + col++; + charPos++; + // replace isolated '\r' by '\n' in order to make + // eol handling uniform across Windows, Unix and Mac + if (ch == '\r' && buffer.Peek() != '\n') + ch = EOL; + if (ch == EOL) { + line++; + col = 0; + } + } + + } + + void AddCh() { + if (tlen >= tval.length) { + char[] newBuf = new char[2 * tval.length]; + System.arraycopy(tval, 0, newBuf, 0, tval.length); + tval = newBuf; + } + if (ch != Buffer.EOF) { + tval[tlen++] = (char)ch; + + NextCh(); + } + } + + + + void CheckLiteral() { + String val = t.val; + + Object kind = literals.get(val); + if (kind != null) { + t.kind = ((Integer) kind).intValue(); + } + } + + Token NextToken() { + while (ch == ' ' || + false + ) NextCh(); + + int recKind = noSym; + int recEnd = pos; + t = new Token(); + t.pos = pos; + t.col = col; + t.line = line; + t.charPos = charPos; + int state = start.state(ch); + tlen = 0; + AddCh(); + + loop: for (;;) { + switch (state) { + case -1: { + t.kind = eofSym; + break loop; + } // NextCh already done + case 0: { + if (recKind != noSym) { + tlen = recEnd - t.pos; + SetScannerBehindT(); + } + t.kind = recKind; + break loop; + } // NextCh already done + case 1: + recEnd = pos; recKind = 1; + if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;} + else {t.kind = 1; break loop;} + case 2: + recEnd = pos; recKind = 2; + if (ch >= '0' && ch <= '9') {AddCh(); state = 2; break;} + else {t.kind = 2; break loop;} + case 3: + {t.kind = 2; break loop;} + case 4: + {t.kind = 5; break loop;} + case 5: + {t.kind = 7; break loop;} + case 6: + if (ch == '=') {AddCh(); state = 7; break;} + else {state = 0; break;} + case 7: + {t.kind = 8; break loop;} + case 8: + {t.kind = 9; break loop;} + case 9: + {t.kind = 10; break loop;} + case 10: + {t.kind = 11; break loop;} + case 11: + {t.kind = 12; break loop;} + case 12: + {t.kind = 13; break loop;} + case 13: + recEnd = pos; recKind = 3; + if (ch == '=') {AddCh(); state = 8; break;} + else {t.kind = 3; break loop;} + case 14: + recEnd = pos; recKind = 4; + if (ch == '=') {AddCh(); state = 4; break;} + else {t.kind = 4; break loop;} + case 15: + recEnd = pos; recKind = 6; + if (ch == '=') {AddCh(); state = 5; break;} + else {t.kind = 6; break loop;} + + } + } + t.val = new String(tval, 0, tlen); + return t; + } + + private void SetScannerBehindT() { + buffer.setPos(t.pos); + NextCh(); + line = t.line; + col = t.col; + charPos = t.charPos; + for (int i = 0; i < tlen; i++) + NextCh(); + } + + // get the next token (possibly a token already seen during peeking) + public Token Scan() { + if (tokens.next == null) { + return NextToken(); + } else { + pt = tokens = tokens.next; + return tokens; + } + } + + // get the next token, ignore pragmas + public Token Peek() { + do { + if (pt.next == null) { + pt.next = NextToken(); + } + pt = pt.next; + } while (pt.kind > maxT); // skip pragmas + + return pt; + } + + // make sure that peeking starts at current scan position + public void ResetPeek() { + pt = tokens; + } + +} // end Scanner diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/DSLExpressionGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/DSLExpressionGenerator.java Fri Jan 23 02:55:23 2015 +0100 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2015, 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.generator; + +import java.util.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.expression.*; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Binary; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Call; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.DSLExpressionVisitor; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.IntLiteral; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable; +import com.oracle.truffle.dsl.processor.java.model.*; + +public class DSLExpressionGenerator implements DSLExpressionVisitor { + + private final Map bindings; + private final CodeTree root; + private final Deque stack = new ArrayDeque<>(); + + public DSLExpressionGenerator(CodeTree root, Map bindings) { + this.bindings = bindings; + this.root = root; + } + + public void visitBinary(Binary binary) { + CodeTree right = stack.pop(); + CodeTree left = stack.pop(); + stack.push(combine(left, string(" " + binary.getOperator() + " "), right)); + } + + public void visitCall(Call call) { + ExecutableElement method = call.getResolvedMethod(); + CodeTree[] parameters = new CodeTree[method.getParameters().size()]; + for (int i = 0; i < parameters.length; i++) { + parameters[parameters.length - i - 1] = pop(); + } + + CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); + + if (call.getReceiver() == null) { + if (isStatic(method)) { + builder.startStaticCall(method); + } else { + if (root != null) { + builder.tree(root).string("."); + } + builder.startCall(method.getSimpleName().toString()); + } + } else { + if (isStatic(method)) { + throw new AssertionError("Static calls must not have receivers."); + } + builder.startCall(pop(), method.getSimpleName().toString()); + } + for (CodeTree parameter : parameters) { + builder.tree(parameter); + } + builder.end(); + + push(builder.build()); + } + + public void visitIntLiteral(IntLiteral binary) { + push(string(binary.getLiteral())); + } + + public void visitNegate(Negate negate) { + push(combine(string("!"), pop())); + } + + public void visitVariable(Variable variable) { + VariableElement resolvedVariable = variable.getResolvedVariable(); + CodeTree tree; + if (variable.getReceiver() == null) { + + if (isStatic(resolvedVariable)) { + tree = staticReference(resolvedVariable); + } else { + tree = bindings.get(variable); + boolean bound = true; + if (tree == null) { + tree = string(resolvedVariable.getSimpleName().toString()); + bound = false; + } + if (root != null && !bound) { + tree = combine(root, string("."), tree); + } + } + } else { + if (isStatic(resolvedVariable)) { + throw new AssertionError("Static variables cannot have receivers."); + } + tree = combine(pop(), string("."), string(resolvedVariable.getSimpleName().toString())); + } + push(tree); + } + + private static boolean isStatic(Element element) { + return element.getModifiers().contains(Modifier.STATIC); + } + + private static CodeTree combine(CodeTree tree1, CodeTree tree2) { + return new CodeTreeBuilder(null).startGroup().tree(tree1).tree(tree2).end().build(); + } + + private static CodeTree combine(CodeTree tree1, CodeTree tree2, CodeTree tree3) { + return new CodeTreeBuilder(null).startGroup().tree(tree1).tree(tree2).tree(tree3).end().build(); + } + + private static CodeTree string(String s) { + return CodeTreeBuilder.singleString(s); + } + + private static CodeTree staticReference(VariableElement var) { + return CodeTreeBuilder.createBuilder().staticReference(var.asType(), var.getSimpleName().toString()).build(); + } + + private void push(CodeTree tree) { + stack.push(tree); + } + + private CodeTree pop() { + return stack.pop(); + } + + public static CodeTree write(DSLExpression expression, CodeTree root, Map bindings) { + DSLExpressionGenerator writer = new DSLExpressionGenerator(root, bindings); + expression.accept(writer); + return writer.pop(); + } + +} diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Fri Jan 23 02:55:23 2015 +0100 @@ -43,6 +43,8 @@ import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.expression.*; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable; import com.oracle.truffle.dsl.processor.java.*; import com.oracle.truffle.dsl.processor.java.model.*; import com.oracle.truffle.dsl.processor.model.*; @@ -51,7 +53,7 @@ public class NodeGenFactory { - private static final String FRAME_VALUE = "frameValue"; + private static final String FRAME_VALUE = TemplateMethod.FRAME_NAME; private static final String NAME_SUFFIX = "_"; @@ -318,7 +320,7 @@ return constructor; } - private static boolean mayBeExcluded(SpecializationData specialization) { + public static boolean mayBeExcluded(SpecializationData specialization) { return !specialization.getExceptions().isEmpty() || !specialization.getExcludedBy().isEmpty(); } @@ -1061,7 +1063,7 @@ return true; } - if (!fastPath && group.getSpecialization() != null && !group.getSpecialization().getExceptions().isEmpty()) { + if (!fastPath && group.getSpecialization() != null && mayBeExcluded(group.getSpecialization())) { return true; } @@ -1438,7 +1440,7 @@ List elseGuardExpressions = group.findElseConnectableGuards(); List guardExpressions = new ArrayList<>(group.getGuards()); guardExpressions.removeAll(elseGuardExpressions); - CodeTree methodGuards = createMethodGuardCheck(guardExpressions, currentValues); + CodeTree methodGuards = createMethodGuardCheck(guardExpressions, group.getSpecialization(), currentValues); if (!group.getAssumptions().isEmpty()) { if (execution.isFastPath() && !forType.isGeneric()) { @@ -1533,14 +1535,13 @@ } private boolean isTypeGuardUsedInAnyGuardBelow(SpecializationGroup group, LocalContext currentValues, TypeGuard typeGuard) { - NodeExecutionData execution = node.getChildExecutions().get(typeGuard.getSignatureIndex()); + LocalVariable localVariable = currentValues.getValue(typeGuard.getSignatureIndex()); for (GuardExpression guard : group.getGuards()) { - List guardParameters = guard.getResolvedGuard().findByExecutionData(execution); - TypeData sourceType = currentValues.getValue(typeGuard.getSignatureIndex()).getType(); - - for (Parameter guardParameter : guardParameters) { - if (sourceType.needsCastTo(guardParameter.getType())) { + Map boundValues = bindLocalValues(guard.getExpression(), group.getSpecialization(), currentValues); + for (Variable var : guard.getExpression().findBoundVariables()) { + LocalVariable target = boundValues.get(var); + if (localVariable.getName().equals(target.getName())) { return true; } } @@ -1946,20 +1947,57 @@ return builder.build(); } - private CodeTree createMethodGuardCheck(List guardExpressions, LocalContext currentValues) { + private CodeTree createMethodGuardCheck(List guardExpressions, SpecializationData specialization, LocalContext currentValues) { CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); String and = ""; for (GuardExpression guard : guardExpressions) { + DSLExpression expression = guard.getExpression(); + Map bindings = bindLocalValues(expression, specialization, currentValues); + Map resolvedBindings = new HashMap<>(); + for (Variable variable : bindings.keySet()) { + LocalVariable localVariable = bindings.get(variable); + CodeTree resolved = CodeTreeBuilder.singleString(localVariable.getName()); + if (!ElementUtils.typeEquals(variable.getResolvedType(), localVariable.getTypeMirror())) { + resolved = CodeTreeBuilder.createBuilder().cast(variable.getResolvedType(), resolved).build(); + } + resolvedBindings.put(variable, resolved); + } + builder.string(and); - if (guard.isNegated()) { - builder.string("!"); - } - builder.tree(callTemplateMethod(accessParent(null), guard.getResolvedGuard(), currentValues)); + builder.tree(DSLExpressionGenerator.write(expression, accessParent(null), resolvedBindings)); and = " && "; } return builder.build(); } + private static Map bindLocalValues(DSLExpression expression, SpecializationData specialization, LocalContext currentValues) throws AssertionError { + Map bindings = new HashMap<>(); + + List boundVariables = expression.findBoundVariables(); + if (specialization == null && !boundVariables.isEmpty()) { + throw new AssertionError("Cannot bind guard variable in non-specialization group. yet."); + } + + // resolve bindings for local context + for (Variable variable : boundVariables) { + Parameter resolvedParameter = specialization.findByVariable(variable.getResolvedVariable()); + if (resolvedParameter != null) { + LocalVariable localVariable; + if (resolvedParameter.getSpecification().isSignature()) { + NodeExecutionData execution = resolvedParameter.getSpecification().getExecution(); + localVariable = currentValues.getValue(execution); + } else { + localVariable = currentValues.get(resolvedParameter.getLocalName()); + } + if (localVariable == null) { + throw new AssertionError("Could not resolve local for execution."); + } + bindings.put(variable, localVariable); + } + } + return bindings; + } + private CodeTree[] createTypeCheckAndCast(List typeGuards, Set castGuards, LocalContext currentValues, SpecializationExecution specializationExecution) { CodeTreeBuilder checksBuilder = CodeTreeBuilder.createBuilder(); CodeTreeBuilder castsBuilder = CodeTreeBuilder.createBuilder(); diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Fri Jan 23 02:55:23 2015 +0100 @@ -181,8 +181,17 @@ } public static String getReadableSignature(ExecutableElement method) { - // TODO toString does not guarantee a good signature - return method.toString(); + StringBuilder builder = new StringBuilder(); + builder.append(method.getSimpleName().toString()); + builder.append("("); + String sep = ""; + for (VariableElement var : method.getParameters()) { + builder.append(sep); + builder.append(getSimpleName(var.asType())); + sep = ", "; + } + builder.append(")"); + return builder.toString(); } public static boolean hasError(TypeMirror mirror) { @@ -680,6 +689,8 @@ return pack.getQualifiedName().toString(); case ARRAY: return getSimpleName(((ArrayType) mirror).getComponentType()); + case EXECUTABLE: + return null; default: throw new RuntimeException("Unknown type specified " + mirror.getKind()); } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java Fri Jan 23 02:55:23 2015 +0100 @@ -77,11 +77,11 @@ } public static CodeTree singleString(String s) { - return new CodeTreeBuilder(null).string(s).getTree(); + return createBuilder().string(s).build(); } public static CodeTree singleType(TypeMirror s) { - return new CodeTreeBuilder(null).type(s).getTree(); + return createBuilder().type(s).build(); } private CodeTreeBuilder push(CodeTreeKind kind) { diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AssumptionExpression.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AssumptionExpression.java Fri Jan 23 02:55:23 2015 +0100 @@ -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.model; + +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.expression.*; +import com.oracle.truffle.dsl.processor.java.*; + +public final class AssumptionExpression extends MessageContainer { + + private final TemplateMethod source; + private final DSLExpression expression; + + public AssumptionExpression(TemplateMethod source, DSLExpression expression) { + this.source = source; + this.expression = expression; + } + + @Override + public Element getMessageElement() { + return source.getMessageElement(); + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return source.getMessageAnnotation(); + } + + @Override + public AnnotationValue getMessageAnnotationValue() { + return ElementUtils.getAnnotationValue(getMessageAnnotation(), "assumptions"); + } + + public DSLExpression getExpression() { + return expression; + } + +} diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CacheExpression.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CacheExpression.java Fri Jan 23 02:55:23 2015 +0100 @@ -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.model; + +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.expression.*; +import com.oracle.truffle.dsl.processor.java.*; + +public final class CacheExpression extends MessageContainer { + + private final DSLExpression expression; + private final Parameter sourceParameter; + private final AnnotationMirror sourceAnnotationMirror; + + public CacheExpression(Parameter sourceParameter, AnnotationMirror sourceAnnotationMirror, DSLExpression expression) { + this.sourceParameter = sourceParameter; + this.expression = expression; + this.sourceAnnotationMirror = sourceAnnotationMirror; + } + + @Override + public Element getMessageElement() { + return sourceParameter.getVariableElement(); + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return sourceAnnotationMirror; + } + + @Override + public AnnotationValue getMessageAnnotationValue() { + return ElementUtils.getAnnotationValue(getMessageAnnotation(), "value"); + } + + public DSLExpression getExpression() { + return expression; + } + +} diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java Fri Jan 23 02:55:23 2015 +0100 @@ -85,8 +85,4 @@ return super.equals(obj); } - public Parameter getFrame() { - return findParameter("frameValue"); - } - } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardData.java Thu Jan 22 20:44:24 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.model; - -import java.util.*; - -public class GuardData extends TemplateMethod { - - private List impliesExpressions; - - public GuardData(TemplateMethod method, List impliesExpressions) { - super(method); - this.impliesExpressions = impliesExpressions; - } - - public List getImpliesExpressions() { - return impliesExpressions; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof GuardData) { - GuardData other = (GuardData) obj; - return getMethod().equals(other.getMethod()); - } - return false; - } - - @Override - public int hashCode() { - return getMethod().hashCode(); - } - -} diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java Fri Jan 23 02:55:23 2015 +0100 @@ -24,120 +24,63 @@ import java.util.*; -public final class GuardExpression { - - private GuardData resolvedGuard; - private NodeExecutionData[] resolvedChildren; - - private final String guardName; - private final boolean negated; - private final String[] childNames; +import javax.lang.model.element.*; - public GuardExpression(String expression, boolean allowArguments) { - String exp = expression; - if (exp.startsWith("!")) { - exp = exp.substring(1, exp.length()); - negated = true; - } else { - negated = false; - } +import com.oracle.truffle.dsl.processor.expression.*; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate; +import com.oracle.truffle.dsl.processor.java.*; - int argumentStart = exp.indexOf('('); - int endIndex = exp.lastIndexOf(')'); - if (allowArguments && argumentStart != -1 && endIndex != -1) { - guardName = exp.substring(0, argumentStart).trim(); - String arguments = exp.substring(argumentStart + 1, endIndex); - String[] children = arguments.split(","); - for (int i = 0; i < children.length; i++) { - children[i] = children[i].trim(); - } - if (children.length == 1 && children[0].isEmpty()) { - childNames = new String[0]; - } else { - childNames = children; - } - } else { - guardName = exp; - childNames = null; - } +public final class GuardExpression extends MessageContainer { + + private final TemplateMethod source; + private final DSLExpression expression; + + public GuardExpression(TemplateMethod source, DSLExpression expression) { + this.source = source; + this.expression = expression; } - public String[] getChildNames() { - return childNames; - } - - public boolean isResolved() { - return resolvedGuard != null; + @Override + public Element getMessageElement() { + return source.getMessageElement(); } - public String getGuardName() { - return guardName; - } - - public NodeExecutionData[] getResolvedChildren() { - return resolvedChildren; - } - - public void setResolvedChildren(NodeExecutionData[] resolvedChildren) { - this.resolvedChildren = resolvedChildren; - } - - public void setResolvedGuard(GuardData guard) { - this.resolvedGuard = guard; + @Override + public AnnotationMirror getMessageAnnotation() { + return source.getMessageAnnotation(); } @Override - public boolean equals(Object obj) { - if (this == obj) { + public AnnotationValue getMessageAnnotationValue() { + return ElementUtils.getAnnotationValue(getMessageAnnotation(), "guards"); + } + + public DSLExpression getExpression() { + return expression; + } + + public boolean equalsNegated(GuardExpression other) { + boolean negated = false; + DSLExpression thisExpression = expression; + if (thisExpression instanceof Negate) { + negated = true; + thisExpression = ((Negate) thisExpression).getReceiver(); + } + + boolean otherNegated = false; + DSLExpression otherExpression = other.expression; + if (otherExpression instanceof Negate) { + otherNegated = true; + otherExpression = ((Negate) otherExpression).getReceiver(); + } + return Objects.equals(thisExpression, otherExpression) && negated != otherNegated; + } + + public boolean implies(GuardExpression other) { + if (Objects.equals(expression, other.expression)) { return true; - } else if (obj instanceof GuardExpression) { - GuardExpression other = (GuardExpression) obj; - if (isResolved() && other.isResolved()) { - return resolvedGuard.equals(other.resolvedGuard) && negated == other.negated && Arrays.equals(resolvedChildren, other.resolvedChildren); - } else { - boolean equal = guardName.equals(other.guardName) && negated == other.negated; - if (childNames != null && other.childNames != null) { - equal &= Arrays.equals(childNames, other.childNames); - } - return equal; - } } return false; } - @Override - public int hashCode() { - return Objects.hash(guardName, negated, resolvedGuard, resolvedChildren); - } - - public boolean implies(GuardExpression other) { - if (equals(other)) { - return true; - } - - if (isResolved() && other.isResolved()) { - for (GuardExpression implies : getResolvedGuard().getImpliesExpressions()) { - if (implies.getGuardName().equals(other.getGuardName())) { - if (implies.isNegated() == other.isNegated()) { - return true; - } - } - } - } - return false; - } - - @Override - public String toString() { - return (negated ? "!" : "") + guardName; - } - - public boolean isNegated() { - return negated; - } - - public GuardData getResolvedGuard() { - return resolvedGuard; - } - } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java Fri Jan 23 02:55:23 2015 +0100 @@ -148,7 +148,7 @@ if (!specialization.isReachable()) { continue; } - if (specialization.isFrameUsedByGuard()) { + if (specialization.isFrameUsed()) { return true; } } @@ -239,7 +239,7 @@ public boolean supportsFrame() { if (executableTypes != null) { for (ExecutableTypeData execType : getExecutableTypes(-1)) { - if (execType.findParameter("frameValue") == null) { + if (execType.findParameter(TemplateMethod.FRAME_NAME) == null) { return false; } } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java Fri Jan 23 02:55:23 2015 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.dsl.processor.model; +import javax.lang.model.element.*; import javax.lang.model.type.*; import com.oracle.truffle.dsl.processor.java.*; @@ -36,6 +37,8 @@ private final int typeVarArgsIndex; private final TypeMirror actualType; + private VariableElement variableElement; + public Parameter(ParameterSpec specification, TypeMirror actualType, int specificationVarArgsIndex, int typeVarArgsIndex) { this.specification = specification; this.actualType = actualType; @@ -67,6 +70,15 @@ this.specificationVarArgsIndex = parameter.specificationVarArgsIndex; this.localName = parameter.localName; this.typeVarArgsIndex = parameter.typeVarArgsIndex; + this.variableElement = parameter.variableElement; + } + + public void setVariableElement(VariableElement variableElement) { + this.variableElement = variableElement; + } + + public VariableElement getVariableElement() { + return variableElement; } public int getTypeVarArgsIndex() { diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Fri Jan 23 02:55:23 2015 +0100 @@ -24,8 +24,9 @@ import java.util.*; +import javax.lang.model.element.*; + import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.java.*; public final class SpecializationData extends TemplateMethod { @@ -40,6 +41,8 @@ private final SpecializationKind kind; private final List exceptions; private List guards = Collections.emptyList(); + private List caches = Collections.emptyList(); + private List assumptionExpressions = Collections.emptyList(); private List shortCircuits; private List assumptions = Collections.emptyList(); private final Set contains = new TreeSet<>(); @@ -62,6 +65,15 @@ } } + public Parameter findByVariable(VariableElement variable) { + for (Parameter parameter : getParameters()) { + if (parameter.getVariableElement() == variable) { + return parameter; + } + } + return null; + } + public void setInsertBefore(SpecializationData insertBefore) { this.insertBefore = insertBefore; } @@ -113,11 +125,7 @@ sinks.addAll(exceptions); } if (guards != null) { - for (GuardExpression guard : guards) { - if (guard.isResolved()) { - sinks.add(guard.getResolvedGuard()); - } - } + sinks.addAll(guards); } return sinks; } @@ -284,20 +292,24 @@ return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature()); } - public boolean isFrameUsedByGuard() { - for (GuardExpression guard : getGuards()) { - if (guard.getResolvedGuard() == null) { - continue; - } + public boolean isFrameUsed() { + return getFrame() != null; + } + + public List getCaches() { + return caches; + } - for (Parameter param : guard.getResolvedGuard().getParameters()) { - if (ElementUtils.typeEquals(param.getType(), getNode().getFrameType())) { - return true; - } - } - } + public void setCaches(List caches) { + this.caches = caches; + } - return false; + public void setAssumptionExpressions(List assumptionExpressions) { + this.assumptionExpressions = assumptionExpressions; + } + + public List getAssumptionExpressions() { + return assumptionExpressions; } public boolean isReachableAfter(SpecializationData prev) { diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java Fri Jan 23 02:55:23 2015 +0100 @@ -35,6 +35,7 @@ */ public class TemplateMethod extends MessageContainer implements Comparable { + public static final String FRAME_NAME = "frameValue"; public static final int NO_NATURAL_ORDER = -1; private String id; @@ -68,6 +69,10 @@ this.id = id; } + public final Parameter getFrame() { + return findParameter(FRAME_NAME); + } + public String createReferenceName() { if (getMethod() == null) { return "-"; diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java Thu Jan 22 20:44:24 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.parser; - -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.java.*; -import com.oracle.truffle.dsl.processor.model.*; - -public class GuardParser extends NodeMethodParser { - - private final GuardExpression expression; - private final TemplateMethod guardedMethod; - - public GuardParser(ProcessorContext context, NodeData node, TemplateMethod compatibleSource, GuardExpression expression) { - super(context, node); - this.expression = expression; - this.guardedMethod = compatibleSource; - getParser().setEmitErrors(false); - setParseNullOnError(false); - } - - @Override - protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) { - return super.createValueParameterSpec(execution); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null); - spec.setIgnoreAdditionalSpecifications(true); - spec.getRequired().clear(); - - if (expression.getResolvedChildren() != null) { - for (NodeExecutionData execution : expression.getResolvedChildren()) { - List foundInGuardedMethod = guardedMethod.findByExecutionData(execution); - for (Parameter guardedParameter : foundInGuardedMethod) { - spec.addRequired(createParameterSpec(guardedParameter)); - } - } - } else { - for (Parameter parameter : guardedMethod.getRequiredParameters()) { - spec.addRequired(createParameterSpec(parameter)); - } - } - - return spec; - } - - private ParameterSpec createParameterSpec(Parameter parameter) { - List typeMirrors = ElementUtils.getAssignableTypes(getContext(), parameter.getType()); - Set typeIds = new HashSet<>(); - for (TypeMirror typeMirror : typeMirrors) { - typeIds.add(ElementUtils.getUniqueIdentifier(typeMirror)); - } - if (parameter.getSpecification().isSignature()) { - typeIds.retainAll(getTypeSystem().getTypeIdentifiers()); - } - - return new ParameterSpec(parameter.getSpecification(), typeMirrors, typeIds); - } - - @Override - protected List nodeTypeMirrors(NodeData nodeData) { - Set typeMirrors = new LinkedHashSet<>(); - typeMirrors.addAll(nodeData.getTypeSystem().getPrimitiveTypeMirrors()); - typeMirrors.addAll(nodeData.getTypeSystem().getBoxedTypeMirrors()); - return new ArrayList<>(typeMirrors); - } - - @Override - protected Set nodeTypeIdentifiers(NodeData nodeData) { - return nodeData.getTypeSystem().getTypeIdentifiers(); - } - - @Override - protected ParameterSpec createReturnParameterSpec() { - return new ParameterSpec("returnType", getContext().getType(boolean.class)); - } - - @Override - public boolean isParsable(ExecutableElement method) { - return true; - } - - @Override - public GuardData create(TemplateMethod method, boolean invalid) { - Implies impliesAnnotation = method.getMethod().getAnnotation(Implies.class); - String[] impliesExpressions = new String[0]; - if (impliesAnnotation != null) { - impliesExpressions = impliesAnnotation.value(); - } - List guardExpressions = new ArrayList<>(); - for (String string : impliesExpressions) { - guardExpressions.add(new GuardExpression(string, false)); - } - return new GuardData(method, guardExpressions); - } - - @Override - public Class getAnnotationType() { - return null; - } - -} diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java Fri Jan 23 02:55:23 2015 +0100 @@ -81,7 +81,15 @@ parameterTypes.add(var.asType()); } - return parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, parameterTypes); + TemplateMethod templateMethod = parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, parameterTypes); + if (templateMethod != null) { + for (int i = 0; i < templateMethod.getParameters().size(); i++) { + if (i < method.getParameters().size()) { + templateMethod.getParameters().get(i).setVariableElement(method.getParameters().get(i)); + } + } + } + return templateMethod; } public TemplateMethod parseImpl(MethodSpec methodSpecification, int naturalOrder, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType, diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Fri Jan 23 02:55:23 2015 +0100 @@ -33,6 +33,7 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.expression.*; import com.oracle.truffle.dsl.processor.java.*; import com.oracle.truffle.dsl.processor.java.compiler.*; import com.oracle.truffle.dsl.processor.model.*; @@ -174,8 +175,10 @@ return node; } - private ArrayList loadMembers(TypeElement templateType) { - return new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType)); + private List loadMembers(TypeElement templateType) { + List members = new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType)); + + return members; } private boolean containsSpecializations(List elements) { @@ -687,7 +690,11 @@ return; } - initializeGuards(elements, node); + initializeExpressions(elements, node); + if (node.hasErrors()) { + return; + } + initializeGeneric(node); initializeUninitialized(node); initializeOrder(node); @@ -775,11 +782,11 @@ AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains"); if (foundSpecialization.compareTo(specialization) > 0) { specialization.addError(value, "The contained specialization '%s' must be declared before the containing specialization.", includeName); - } else { - specialization.addError(value, - "The contained specialization '%s' is not fully compatible. The contained specialization must be strictly more generic than the containing one.", - includeName); - } + }/* + * else { specialization.addError(value, + * "The contained specialization '%s' is not fully compatible. The contained specialization must be strictly more generic than the containing one." + * , includeName); } + */ } resolvedSpecializations.add(foundSpecialization); @@ -925,74 +932,68 @@ return changed; } - private void initializeGuards(List elements, NodeData node) { - Map> potentialGuards = new HashMap<>(); - for (SpecializationData specialization : node.getSpecializations()) { - for (GuardExpression exp : specialization.getGuards()) { - potentialGuards.put(exp.getGuardName(), null); - } - } + private void initializeExpressions(List elements, NodeData node) { + List members = filterNotAccessibleElements(node.getTemplateType(), elements); - TypeMirror booleanType = context.getType(boolean.class); - for (ExecutableElement potentialGuard : ElementFilter.methodsIn(elements)) { - if (potentialGuard.getModifiers().contains(Modifier.PRIVATE)) { - continue; - } - String methodName = potentialGuard.getSimpleName().toString(); - if (!potentialGuards.containsKey(methodName)) { - continue; - } + final TypeMirror booleanType = context.getType(boolean.class); - if (!ElementUtils.typeEquals(potentialGuard.getReturnType(), booleanType)) { + for (SpecializationData specialization : node.getSpecializations()) { + if (specialization.getMethod() == null) { continue; } - List potentialMethods = potentialGuards.get(methodName); - if (potentialMethods == null) { - potentialMethods = new ArrayList<>(); - potentialGuards.put(methodName, potentialMethods); + List specializationMembers = new ArrayList<>(); + for (Parameter p : specialization.getParameters()) { + VariableElement variableElement = p.getVariableElement(); + if (variableElement == null) { + throw new AssertionError("All parameters must be resolved for " + specialization); + } + + specializationMembers.add(variableElement); } - potentialMethods.add(potentialGuard); - } + specializationMembers.addAll(members); - for (SpecializationData specialization : node.getSpecializations()) { - for (GuardExpression exp : specialization.getGuards()) { - resolveGuardExpression(node, specialization, potentialGuards, exp); + DSLExpressionResolver resolver = new DSLExpressionResolver(context, specializationMembers); + List guardDefinitions = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); + List guardExpressions = new ArrayList<>(); + for (String guard : guardDefinitions) { + GuardExpression guardExpression; + DSLExpression expression = null; + try { + expression = DSLExpression.parse(guard); + expression.accept(resolver); + guardExpression = new GuardExpression(specialization, expression); + if (!ElementUtils.typeEquals(expression.getResolvedType(), booleanType)) { + guardExpression.addError("Incompatible return type %s. Guard expressions must return boolean.", ElementUtils.getSimpleName(expression.getResolvedType())); + } +// guardExpression.addWarning("Expression:%s", expression.toString()); + } catch (InvalidExpressionException e) { + guardExpression = new GuardExpression(specialization, null); + guardExpression.addError("Error parsing expression '%s': %s", guard, e.getMessage()); + } + guardExpressions.add(guardExpression); } + specialization.setGuards(guardExpressions); } } - private void resolveGuardExpression(NodeData node, TemplateMethod source, Map> guards, GuardExpression expression) { - List availableGuards = guards.get(expression.getGuardName()); - if (availableGuards == null) { - source.addError("No compatible guard with method name '%s' found.", expression.getGuardName()); - return; - } + private static List filterNotAccessibleElements(TypeElement templateType, List elements) { + String packageName = ElementUtils.getPackageName(templateType); + List filteredElements = new ArrayList<>(elements); + for (Element element : elements) { + Modifier visibility = ElementUtils.getVisibility(element.getModifiers()); + if (visibility == Modifier.PRIVATE) { + continue; + } else if (visibility == null) { + String elementPackageName = ElementUtils.getPackageName(element.getEnclosingElement().asType()); + if (!Objects.equals(packageName, elementPackageName) && !elementPackageName.equals("java.lang")) { + continue; + } + } - String[] childNames = expression.getChildNames(); - if (childNames != null) { - NodeExecutionData[] resolvedExecutions = new NodeExecutionData[childNames.length]; - for (int i = 0; i < childNames.length; i++) { - String childName = childNames[i]; - NodeExecutionData execution = node.findExecutionByExpression(childName); - if (execution == null) { - source.addError("Guard parameter '%s' for guard '%s' could not be mapped to a declared child node.", childName, expression.getGuardName()); - return; - } - resolvedExecutions[i] = execution; - } - expression.setResolvedChildren(resolvedExecutions); + filteredElements.add(element); } - - GuardParser parser = new GuardParser(context, node, source, expression); - List matchingGuards = parser.parse(availableGuards); - if (!matchingGuards.isEmpty() && matchingGuards.get(0) != null) { - expression.setResolvedGuard(matchingGuards.get(0)); - } else { - MethodSpec spec = parser.createSpecification(source.getMethod(), source.getMarkerAnnotation()); - spec.applyTypeDefinitions("types"); - source.addError("No guard with name '%s' matched the required signature. Expected signature: %n%s", expression.getGuardName(), spec.toSignatureString("guard")); - } + return filteredElements; } private void initializeGeneric(final NodeData node) { diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java Fri Jan 23 02:55:23 2015 +0100 @@ -24,9 +24,7 @@ import java.util.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.generator.*; import com.oracle.truffle.dsl.processor.model.*; import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature; @@ -110,18 +108,35 @@ return null; } + if (previous.mayBeExcluded()) { + return null; + } + /* Guard is else branch can be connected in previous specialization. */ if (elseConnectedGuards.contains(guard)) { return guard; } GuardExpression previousGuard = previous.getGuards().get(elseConnectedGuards.size()); - if (guard.getResolvedGuard().getMethod().equals(previousGuard.getResolvedGuard().getMethod()) && guard.isNegated() != previousGuard.isNegated()) { + if (guard.equalsNegated(previousGuard)) { return guard; } return null; } + private boolean mayBeExcluded() { + if (specialization != null) { + return NodeGenFactory.mayBeExcluded(specialization); + } else { + for (SpecializationGroup group : getChildren()) { + if (group.mayBeExcluded()) { + return true; + } + } + } + return false; + } + private void updateChildren(List childs) { if (!children.isEmpty()) { children.clear(); @@ -204,38 +219,10 @@ // check for guards for required type casts for (Iterator iterator = guardMatches.iterator(); iterator.hasNext();) { GuardExpression guardMatch = iterator.next(); - - int signatureIndex = 0; - for (Parameter parameter : guardMatch.getResolvedGuard().getParameters()) { - signatureIndex++; - if (!parameter.getSpecification().isSignature()) { - continue; - } - - TypeMirror guardType = parameter.getType(); - - // object guards can be safely moved up - if (ElementUtils.isObject(guardType)) { - continue; - } - - // generic guards can be safely moved up - SpecializationData generic = first.node.getGenericSpecialization(); - if (generic != null) { - Parameter genericParameter = generic.findParameter(parameter.getLocalName()); - if (genericParameter != null && ElementUtils.typeEquals(genericParameter.getType(), guardType)) { - continue; - } - } - - // signature index required for moving up guards - if (containsIndex(typeGuardsMatches, signatureIndex) || (first.getParent() != null && first.getParent().containsTypeGuardIndex(signatureIndex))) { - continue; - } - + if (!guardMatch.getExpression().findBoundVariables().isEmpty()) { iterator.remove(); - break; } + // TODO we need to be smarter here with bound parameters. } if (assumptionMatches.isEmpty() && typeGuardsMatches.isEmpty() && guardMatches.isEmpty()) { @@ -252,25 +239,6 @@ return new SpecializationGroup(newChildren, assumptionMatches, typeGuardsMatches, guardMatches); } - private boolean containsTypeGuardIndex(int index) { - if (containsIndex(typeGuards, index)) { - return true; - } - if (parent != null) { - return parent.containsTypeGuardIndex(index); - } - return false; - } - - private static boolean containsIndex(List typeGuards, int signatureIndex) { - for (TypeGuard guard : typeGuards) { - if (guard.signatureIndex == signatureIndex) { - return true; - } - } - return false; - } - public static SpecializationGroup create(SpecializationData specialization) { return new SpecializationGroup(specialization); } diff -r ae81dd154fb6 -r 08aa0372dad4 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java Thu Jan 22 20:44:24 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java Fri Jan 23 02:55:23 2015 +0100 @@ -92,13 +92,6 @@ specialization.setInsertBeforeName(insertBeforeName); } - List guardDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); - List guardExpressions = new ArrayList<>(); - for (String guardDef : guardDefs) { - guardExpressions.add(new GuardExpression(guardDef, true)); - } - specialization.setGuards(guardExpressions); - List containsDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "contains"); Set containsNames = specialization.getContainsNames(); containsNames.clear();