From 954f3a92582314aed4ee644a7dc8e78e2cf4cb37 Mon Sep 17 00:00:00 2001 From: Florian Date: Tue, 25 Oct 2016 19:12:19 +0200 Subject: [PATCH 1/2] implemented support for power operator "^" --- .../sl/nodes/expression/SLPowNode.java | 94 +++++++++++++++++++ tests/LoopPowCall.sl | 20 ++++ tests/Pow.output | 7 ++ tests/Pow.sl | 9 ++ 4 files changed, 130 insertions(+) create mode 100644 src/main/java/com/oracle/truffle/sl/nodes/expression/SLPowNode.java create mode 100644 tests/LoopPowCall.sl create mode 100644 tests/Pow.output create mode 100644 tests/Pow.sl diff --git a/src/main/java/com/oracle/truffle/sl/nodes/expression/SLPowNode.java b/src/main/java/com/oracle/truffle/sl/nodes/expression/SLPowNode.java new file mode 100644 index 000000000..5b56cc2f3 --- /dev/null +++ b/src/main/java/com/oracle/truffle/sl/nodes/expression/SLPowNode.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.truffle.sl.nodes.expression; + +import java.math.BigInteger; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.ExactMath; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.nodes.NodeInfo; +import com.oracle.truffle.sl.nodes.SLBinaryNode; + +/** + * This class is similar to the extensively documented {@link SLMulNode}. + */ +@NodeInfo(shortName = "^") +public abstract class SLPowNode extends SLBinaryNode { + + @Specialization(rewriteOn = ArithmeticException.class) + protected long pow(long left, long right) { +// long res = 1L; +// for(long i=0; i < right; i++) { +// res = ExactMath.multiplyExact(res, left); +// } +// return res; + + if(right < 0L) { + throw new ArithmeticException(); + } + + long p, y; + y = 1L; + p = left; + while (true) { + if ((right & 1L) != 0L) { + y = ExactMath.multiplyExact(p, y); + } + right = right >> 1; + if (right == 0) { + return y; + } + p = ExactMath.multiplyExact(p, p); + } + } + + @Specialization + @TruffleBoundary + protected BigInteger pow(BigInteger left, BigInteger right) { + BigInteger res = BigInteger.ONE; + while (!right.equals(BigInteger.ZERO)) { + res = res.multiply(left); + right = right.subtract(BigInteger.ONE); + } + return res; + } +} diff --git a/tests/LoopPowCall.sl b/tests/LoopPowCall.sl new file mode 100644 index 000000000..f9ef0ae3c --- /dev/null +++ b/tests/LoopPowCall.sl @@ -0,0 +1,20 @@ +function pow(a, b) { + return a ^ b; +} + +function loop(n) { + i = 2; + while (i < n) { + i = pow(i, 2); + } + return i; +} + +function main() { + i = 0; + while (i < 200) { + loop(100000); + i = i + 1; + } + println(loop(100000)); +} diff --git a/tests/Pow.output b/tests/Pow.output new file mode 100644 index 000000000..59e5f2039 --- /dev/null +++ b/tests/Pow.output @@ -0,0 +1,7 @@ +8 +1 +2 +100 +36893488147419103232 +1 +9223372036854775808 diff --git a/tests/Pow.sl b/tests/Pow.sl new file mode 100644 index 000000000..95f0e207e --- /dev/null +++ b/tests/Pow.sl @@ -0,0 +1,9 @@ +function main() { + println(2 ^ 3); + println(2 ^ 0); + println(2 ^ 1); + println(10 ^ 2); + println(2 ^ 65); + println(9223372036854775808 ^ 0); + println(9223372036854775808 ^ 1); +} From ee25e65a2a9df1a1d6bf937b7028d65d4672c068 Mon Sep 17 00:00:00 2001 From: flo Date: Tue, 25 Oct 2016 19:14:46 +0200 Subject: [PATCH 2/2] modifications due to support for power operator "^" --- disassembly.txt | 207 ++++++++++++++++++ generate_parser | 0 .../com/oracle/truffle/sl/parser/Parser.java | 61 ++++-- .../truffle/sl/parser/SLNodeFactory.java | 4 + .../com/oracle/truffle/sl/parser/Scanner.java | 29 +-- .../truffle/sl/parser/SimpleLanguage.atg | 12 +- 6 files changed, 274 insertions(+), 39 deletions(-) create mode 100644 disassembly.txt mode change 100644 => 100755 generate_parser diff --git a/disassembly.txt b/disassembly.txt new file mode 100644 index 000000000..e0e4c1632 --- /dev/null +++ b/disassembly.txt @@ -0,0 +1,207 @@ +CompilerOracle: print *OptimizedCallTarget.callRoot +CompilerOracle: exclude *OptimizedCallTarget.callRoot == running on Graal Truffle Runtime ### Excluding compile: com.oracle.graal.truffle.OptimizedCallTarget::callRoot +[truffle] opt queued root add |ASTSize 11/ 11 |Calls/Thres 1000/ 3 |CallsAndLoop/Thres 1000/ 1000 |Inval# 0 +[truffle] opt start root add |ASTSize 11/ 11 |Calls/Thres 1000/ 3 |CallsAndLoop/Thres 1000/ 1000 |Inval# 0 +Compiled method (JVMCI) 4082 3005 4 com.oracle.graal.truffle.OptimizedCallTarget::callRoot (43 bytes) + total in heap [0x00007ff0e9854d50,0x00007ff0e9855050] = 768 + relocation [0x00007ff0e9854e88,0x00007ff0e9854ea0] = 24 + main code [0x00007ff0e9854ea0,0x00007ff0e9854fc9] = 297 + stub code [0x00007ff0e9854fc9,0x00007ff0e9854fd0] = 7 + oops [0x00007ff0e9854fd0,0x00007ff0e9854fe0] = 16 + metadata [0x00007ff0e9854fe0,0x00007ff0e9854ff0] = 16 + scopes data [0x00007ff0e9854ff0,0x00007ff0e9855008] = 24 + scopes pcs [0x00007ff0e9855008,0x00007ff0e9855048] = 64 + dependencies [0x00007ff0e9855048,0x00007ff0e9855050] = 8 +Loaded disassembler from /home/flo/NetBeansProjects/simplelanguage/graalvm/jre/lib/amd64/hsdis-amd64.so +---------------------------------------------------------------------- +com/oracle/graal/truffle/OptimizedCallTarget.callRoot (root add) [0x00007ff0e9854ea0, 0x00007ff0e9854fd0] 304 bytes +[Disassembling for mach='i386:x86-64'] +[Entry Point] +[Constants] + # {method} {0x00007ff0fd1452d0} 'callRoot' '([Ljava/lang/Object;)Ljava/lang/Object;' in 'com/oracle/graal/truffle/OptimizedCallTarget' + # this: rsi:rsi = 'com/oracle/graal/truffle/OptimizedCallTarget' + # parm0: rdx:rdx = '[Ljava/lang/Object;' + # [sp+0x20] (sp of caller) + 0x00007ff0e9854ea0: mov r10d,DWORD PTR [rsi+0x8] + 0x00007ff0e9854ea4: shl r10,0x3 + 0x00007ff0e9854ea8: cmp rax,r10 + 0x00007ff0e9854eab: jne 0x00007ff0e9047e20 ; {runtime_call} + 0x00007ff0e9854eb1: nop + 0x00007ff0e9854eb2: nop DWORD PTR [rax+0x0] + 0x00007ff0e9854eb9: nop DWORD PTR [rax+0x0] +[Verified Entry Point] + 0x00007ff0e9854ec0: mov DWORD PTR [rsp-0x14000],eax + 0x00007ff0e9854ec7: sub rsp,0x18 + 0x00007ff0e9854ecb: mov QWORD PTR [rsp+0x10],rbp + 0x00007ff0e9854ed0: mov rbx,rdx + 0x00007ff0e9854ed3: mov eax,DWORD PTR [rbx+0x10] + 0x00007ff0e9854ed6: mov rax,QWORD PTR [rax*1+0x10] + 0x00007ff0e9854ede: mov esi,DWORD PTR [rbx+0x14] + 0x00007ff0e9854ee1: mov rsi,QWORD PTR [rsi*1+0x10] + 0x00007ff0e9854ee9: mov rbp,rax + 0x00007ff0e9854eec: add rbp,rsi + 0x00007ff0e9854eef: jo 0x00007ff0e9854f97 + 0x00007ff0e9854ef5: cmp rbp,0xffffffffffffff80 + 0x00007ff0e9854ef9: jl 0x00007ff0e9854f3b + 0x00007ff0e9854eff: cmp rbp,0x7f + 0x00007ff0e9854f03: jg 0x00007ff0e9854f3b + 0x00007ff0e9854f09: mov eax,ebp + 0x00007ff0e9854f0b: add eax,0x80 + 0x00007ff0e9854f11: cmp eax,0x100 + 0x00007ff0e9854f17: jae 0x00007ff0e9854fb5 + 0x00007ff0e9854f1d: movabs rsi,0x80002068 ; {oop(a 'java/lang/Long'[256] )} + 0x00007ff0e9854f27: mov eax,DWORD PTR [rsi+rax*4+0x10] + 0x00007ff0e9854f2b: mov rbp,QWORD PTR [rsp+0x10] + 0x00007ff0e9854f30: add rsp,0x18 + 0x00007ff0e9854f34: test DWORD PTR [rip+0x18dc00cc],eax # 0x00007ff102615006 + ; {poll_return} + 0x00007ff0e9854f3a: ret + 0x00007ff0e9854f3b: mov rax,QWORD PTR [r15+0x60] + 0x00007ff0e9854f3f: mov rsi,rax + 0x00007ff0e9854f42: add rsi,0x18 + 0x00007ff0e9854f46: movabs r10,0x100011558 ; {metadata('java/lang/Long')} + 0x00007ff0e9854f50: cmp rsi,QWORD PTR [r15+0x70] + 0x00007ff0e9854f54: ja 0x00007ff0e9854f8c + 0x00007ff0e9854f5a: mov QWORD PTR [r15+0x60],rsi + 0x00007ff0e9854f5e: prefetchnta BYTE PTR [rax+0xd8] + 0x00007ff0e9854f65: mov rsi,QWORD PTR [r10+0xa8] + 0x00007ff0e9854f6c: mov QWORD PTR [rax],rsi + 0x00007ff0e9854f6f: mov esi,0x200022ab ; {metadata('java/lang/Long')} + 0x00007ff0e9854f74: mov DWORD PTR [rax+0x8],esi + 0x00007ff0e9854f77: mov DWORD PTR [rax+0xc],0x0 + 0x00007ff0e9854f7e: mov QWORD PTR [rax+0x10],0x0 + 0x00007ff0e9854f86: mov QWORD PTR [rax+0x10],rbp + 0x00007ff0e9854f8a: jmp 0x00007ff0e9854f2b + 0x00007ff0e9854f8c: mov rsi,r10 + 0x00007ff0e9854f8f: call 0x00007ff0e984cae0 ; OopMap{rbx=Oop off=244} + ;*aload_1 {reexecute=1 rethrow=0 return_oop=0} + ; - com.oracle.graal.truffle.OptimizedCallTarget::callRoot@0 (line 208) + ; {runtime_call} + 0x00007ff0e9854f94: nop + 0x00007ff0e9854f95: jmp 0x00007ff0e9854f86 + 0x00007ff0e9854f97: mov r10d,0xffffff95 + 0x00007ff0e9854f9d: mov DWORD PTR [r15+0x29c],r10d + 0x00007ff0e9854fa4: mov QWORD PTR [r15+0x2a8],0x0 + 0x00007ff0e9854faf: call 0x00007ff0e90490be ; OopMap{rbx=Oop off=276} + ;*aload_1 {reexecute=1 rethrow=0 return_oop=0} + ; - com.oracle.graal.truffle.OptimizedCallTarget::callRoot@0 (line 208) + ; {runtime_call} + 0x00007ff0e9854fb4: nop + 0x00007ff0e9854fb5: mov r10d,0xffffffe5 + 0x00007ff0e9854fbb: jmp 0x00007ff0e9854f9d +[Exception Handler] + 0x00007ff0e9854fbd: call 0x00007ff0e91303e0 ; {runtime_call} + 0x00007ff0e9854fc2: nop +[Deopt Handler Code] + 0x00007ff0e9854fc3: call 0x00007ff0e9048fc0 ; {runtime_call} + 0x00007ff0e9854fc8: nop +[Stub Code] + 0x00007ff0e9854fc9: hlt + 0x00007ff0e9854fca: hlt + 0x00007ff0e9854fcb: hlt + 0x00007ff0e9854fcc: hlt + 0x00007ff0e9854fcd: hlt + 0x00007ff0e9854fce: hlt + 0x00007ff0e9854fcf: hlt +OopMapSet contains 2 OopMaps + +#0 +OopMap{rbx=Oop off=244} +#1 +OopMap{rbx=Oop off=276} +[truffle] opt done root add |ASTSize 11/ 11 |Time 352( 91+262 )ms |DirectCallNodes I 0/D 0 |GraalNodes 18/ 93 |CodeSize 297 |Source LoopCall.sl:1 +[truffle] opt start root loop |ASTSize 29/ 29 |Calls/Thres 3/ 3 |CallsAndLoop/Thres 2001/ 1010 |Inval# 0 +[truffle] opt queued root loop |ASTSize 29/ 29 |Calls/Thres 3/ 3 |CallsAndLoop/Thres 2001/ 1010 |Inval# 0 +Compiled method (JVMCI) 4888 3542 4 com.oracle.graal.truffle.OptimizedCallTarget::callRoot (43 bytes) + total in heap [0x00007ff0e9a08cd0,0x00007ff0e9a09090] = 960 + relocation [0x00007ff0e9a08e08,0x00007ff0e9a08e20] = 24 + main code [0x00007ff0e9a08e20,0x00007ff0e9a08f04] = 228 + stub code [0x00007ff0e9a08f04,0x00007ff0e9a08f08] = 4 + oops [0x00007ff0e9a08f08,0x00007ff0e9a08f60] = 88 + metadata [0x00007ff0e9a08f60,0x00007ff0e9a08fa8] = 72 + scopes data [0x00007ff0e9a08fa8,0x00007ff0e9a09058] = 176 + scopes pcs [0x00007ff0e9a09058,0x00007ff0e9a09088] = 48 + dependencies [0x00007ff0e9a09088,0x00007ff0e9a09090] = 8 +---------------------------------------------------------------------- +com/oracle/graal/truffle/OptimizedCallTarget.callRoot (root loop) [0x00007ff0e9a08e20, 0x00007ff0e9a08f08] 232 bytes +[Entry Point] +[Constants] + # {method} {0x00007ff0fd1452d0} 'callRoot' '([Ljava/lang/Object;)Ljava/lang/Object;' in 'com/oracle/graal/truffle/OptimizedCallTarget' + # this: rsi:rsi = 'com/oracle/graal/truffle/OptimizedCallTarget' + # parm0: rdx:rdx = '[Ljava/lang/Object;' + # [sp+0x20] (sp of caller) + 0x00007ff0e9a08e20: mov r10d,DWORD PTR [rsi+0x8] + 0x00007ff0e9a08e24: shl r10,0x3 + 0x00007ff0e9a08e28: cmp rax,r10 + 0x00007ff0e9a08e2b: jne 0x00007ff0e9047e20 ; {runtime_call} + 0x00007ff0e9a08e31: nop + 0x00007ff0e9a08e32: nop DWORD PTR [rax+0x0] + 0x00007ff0e9a08e39: nop DWORD PTR [rax+0x0] +[Verified Entry Point] + 0x00007ff0e9a08e40: mov DWORD PTR [rsp-0x14000],eax + 0x00007ff0e9a08e47: sub rsp,0x18 + 0x00007ff0e9a08e4b: mov QWORD PTR [rsp+0x10],rbp + 0x00007ff0e9a08e50: mov esi,DWORD PTR [rdx+0x10] + 0x00007ff0e9a08e53: mov rbx,QWORD PTR [rsi*1+0x10] + 0x00007ff0e9a08e5b: test rbx,rbx + 0x00007ff0e9a08e5e: mov rbp,0x0 + 0x00007ff0e9a08e65: cmovg rbp,rbx + 0x00007ff0e9a08e69: cmp rbp,0x7f + 0x00007ff0e9a08e6d: ja 0x00007ff0e9a08e99 + 0x00007ff0e9a08e73: movabs rax,0x80002068 ; {oop(a 'java/lang/Long'[256] )} + 0x00007ff0e9a08e7d: mov esi,ebp + 0x00007ff0e9a08e7f: add esi,0x80 + 0x00007ff0e9a08e85: mov eax,DWORD PTR [rax+rsi*4+0x10] + 0x00007ff0e9a08e89: mov rbp,QWORD PTR [rsp+0x10] + 0x00007ff0e9a08e8e: add rsp,0x18 + 0x00007ff0e9a08e92: test DWORD PTR [rip+0x18c0c16e],eax # 0x00007ff102615006 + ; {poll_return} + 0x00007ff0e9a08e98: ret + 0x00007ff0e9a08e99: mov rax,QWORD PTR [r15+0x60] + 0x00007ff0e9a08e9d: mov r10,rax + 0x00007ff0e9a08ea0: add r10,0x18 + 0x00007ff0e9a08ea4: movabs r11,0x100011558 ; {metadata('java/lang/Long')} + 0x00007ff0e9a08eae: cmp r10,QWORD PTR [r15+0x70] + 0x00007ff0e9a08eb2: ja 0x00007ff0e9a08eea + 0x00007ff0e9a08eb8: mov QWORD PTR [r15+0x60],r10 + 0x00007ff0e9a08ebc: prefetchnta BYTE PTR [rax+0xd8] + 0x00007ff0e9a08ec3: mov rsi,QWORD PTR [r11+0xa8] + 0x00007ff0e9a08eca: mov QWORD PTR [rax],rsi + 0x00007ff0e9a08ecd: mov esi,0x200022ab ; {metadata('java/lang/Long')} + 0x00007ff0e9a08ed2: mov DWORD PTR [rax+0x8],esi + 0x00007ff0e9a08ed5: mov DWORD PTR [rax+0xc],0x0 + 0x00007ff0e9a08edc: mov QWORD PTR [rax+0x10],0x0 + 0x00007ff0e9a08ee4: mov QWORD PTR [rax+0x10],rbp + 0x00007ff0e9a08ee8: jmp 0x00007ff0e9a08e89 + 0x00007ff0e9a08eea: mov r13d,esi + 0x00007ff0e9a08eed: mov rsi,r11 + 0x00007ff0e9a08ef0: call 0x00007ff0e984cae0 ; OopMap{r13=Oop off=213} + ;*aload_0 {reexecute=1 rethrow=0 return_oop=0} + ; - com.oracle.graal.truffle.OptimizedOSRLoopNode::executeLoop@56 (line 113) + ; - com.oracle.graal.enterprisegraal.t.c$b::executeLoop@48 (line 155) + ; - com.oracle.truffle.sl.nodes.controlflow.SLWhileNode::executeVoid@5 (line 69) + ; - com.oracle.truffle.sl.nodes.controlflow.SLBlockNode::executeVoid@37 (line 84) + ; - com.oracle.truffle.sl.nodes.controlflow.SLFunctionBodyNode::executeGeneric@5 (line 81) + ; - com.oracle.truffle.sl.nodes.SLRootNode::execute@28 (line 78) + ; - com.oracle.graal.truffle.OptimizedCallTarget::callProxy@9 (line 220) + ; - com.oracle.graal.truffle.OptimizedCallTarget::callRoot@29 (line 212) + ; {runtime_call} + 0x00007ff0e9a08ef5: nop + 0x00007ff0e9a08ef6: jmp 0x00007ff0e9a08ee4 +[Exception Handler] + 0x00007ff0e9a08ef8: call 0x00007ff0e91303e0 ; {runtime_call} + 0x00007ff0e9a08efd: nop +[Deopt Handler Code] + 0x00007ff0e9a08efe: call 0x00007ff0e9048fc0 ; {runtime_call} + 0x00007ff0e9a08f03: nop +[Stub Code] + 0x00007ff0e9a08f04: hlt + 0x00007ff0e9a08f05: hlt + 0x00007ff0e9a08f06: hlt + 0x00007ff0e9a08f07: hlt +OopMapSet contains 1 OopMaps + +#0 +OopMap{r13=Oop off=213} +[truffle] opt done root loop |ASTSize 29/ 40 |Time 125( 89+36 )ms |DirectCallNodes I 1/D 0 |GraalNodes 52/ 94 |CodeSize 228 |Source LoopCall.sl:5 +1000 diff --git a/generate_parser b/generate_parser old mode 100644 new mode 100755 diff --git a/src/main/java/com/oracle/truffle/sl/parser/Parser.java b/src/main/java/com/oracle/truffle/sl/parser/Parser.java index 8600608f1..e89bee4bf 100644 --- a/src/main/java/com/oracle/truffle/sl/parser/Parser.java +++ b/src/main/java/com/oracle/truffle/sl/parser/Parser.java @@ -60,7 +60,7 @@ public class Parser { public static final int _identifier = 1; public static final int _stringLiteral = 2; public static final int _numericLiteral = 3; - public static final int maxT = 34; + public static final int maxT = 35; static final boolean _T = true; static final boolean _x = false; @@ -227,7 +227,7 @@ SLStatementNode Statement(boolean inLoop) { Expect(11); break; } - default: SynErr(35); break; + default: SynErr(36); break; } return result; } @@ -353,7 +353,7 @@ SLExpressionNode Arithmetic() { SLExpressionNode Term() { SLExpressionNode result; - result = Factor(); + result = Pow(); while (la.kind == 28 || la.kind == 29) { if (la.kind == 28) { Get(); @@ -361,6 +361,18 @@ SLExpressionNode Term() { Get(); } Token op = t; + SLExpressionNode right = Pow(); + result = factory.createBinary(op, result, right); + } + return result; + } + + SLExpressionNode Pow() { + SLExpressionNode result; + result = Factor(); + while (la.kind == 30) { + Get(); + Token op = t; SLExpressionNode right = Factor(); result = factory.createBinary(op, result, right); } @@ -377,7 +389,7 @@ SLExpressionNode Factor() { result = MemberExpression(null, null, assignmentName); } else if (StartOf(5)) { result = factory.createRead(assignmentName); - } else SynErr(36); + } else SynErr(37); } else if (la.kind == 2) { Get(); result = factory.createStringLiteral(t, true); @@ -392,7 +404,7 @@ SLExpressionNode Factor() { Expect(7); int length = (t.charPos + t.val.length()) - start; result = factory.createParenExpression(expr, start, length); - } else SynErr(37); + } else SynErr(38); return result; } @@ -420,7 +432,7 @@ SLExpressionNode MemberExpression(SLExpressionNode r, SLExpressionNode assignme Expect(7); Token finalToken = t; result = factory.createCall(receiver, parameters, finalToken); - } else if (la.kind == 30) { + } else if (la.kind == 31) { Get(); SLExpressionNode value = Expression(); if (assignmentName == null) { @@ -430,7 +442,7 @@ SLExpressionNode MemberExpression(SLExpressionNode r, SLExpressionNode assignme } else { result = factory.createWriteProperty(assignmentReceiver, assignmentName, value); } - } else if (la.kind == 31) { + } else if (la.kind == 32) { Get(); if (receiver == null) { receiver = factory.createRead(assignmentName); @@ -438,15 +450,15 @@ SLExpressionNode MemberExpression(SLExpressionNode r, SLExpressionNode assignme Expect(1); nestedAssignmentName = factory.createStringLiteral(t, false); result = factory.createReadProperty(receiver, nestedAssignmentName); - } else if (la.kind == 32) { + } else if (la.kind == 33) { Get(); if (receiver == null) { receiver = factory.createRead(assignmentName); } nestedAssignmentName = Expression(); result = factory.createReadProperty(receiver, nestedAssignmentName); - Expect(33); - } else SynErr(38); + Expect(34); + } else SynErr(39); if (StartOf(4)) { result = MemberExpression(result, receiver, nestedAssignmentName); } @@ -465,12 +477,12 @@ public void Parse() { } 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, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x}, - {_x,_T,_T,_T, _x,_T,_x,_x, _x,_x,_T,_x, _T,_T,_T,_T, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x}, - {_x,_T,_T,_T, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x}, - {_x,_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,_x,_x,_x}, - {_x,_x,_x,_x, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _T,_x,_x,_x}, - {_x,_x,_x,_x, _x,_T,_T,_T, _x,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_x,_x} + {_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x}, + {_x,_T,_T,_T, _x,_T,_x,_x, _x,_x,_T,_x, _T,_T,_T,_T, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x}, + {_x,_T,_T,_T, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x}, + {_x,_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,_x,_x,_x, _x}, + {_x,_x,_x,_x, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_T,_x,_x, _x}, + {_x,_x,_x,_x, _x,_T,_T,_T, _x,_x,_x,_T, _x,_x,_x,_x, _x,_x,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_x, _x} }; @@ -544,15 +556,16 @@ public void SynErr(int line, int col, int n) { case 27: s = "\"-\" expected"; break; case 28: s = "\"*\" expected"; break; case 29: s = "\"/\" expected"; break; - case 30: s = "\"=\" expected"; break; - case 31: s = "\".\" expected"; break; - case 32: s = "\"[\" expected"; break; - case 33: s = "\"]\" expected"; break; - case 34: s = "??? expected"; break; - case 35: s = "invalid Statement"; break; - case 36: s = "invalid Factor"; break; + case 30: s = "\"^\" expected"; break; + case 31: s = "\"=\" expected"; break; + case 32: s = "\".\" expected"; break; + case 33: s = "\"[\" expected"; break; + case 34: s = "\"]\" expected"; break; + case 35: s = "??? expected"; break; + case 36: s = "invalid Statement"; break; case 37: s = "invalid Factor"; break; - case 38: s = "invalid MemberExpression"; break; + case 38: s = "invalid Factor"; break; + case 39: s = "invalid MemberExpression"; break; default: s = "error " + n; break; diff --git a/src/main/java/com/oracle/truffle/sl/parser/SLNodeFactory.java b/src/main/java/com/oracle/truffle/sl/parser/SLNodeFactory.java index 783226951..84e91c985 100644 --- a/src/main/java/com/oracle/truffle/sl/parser/SLNodeFactory.java +++ b/src/main/java/com/oracle/truffle/sl/parser/SLNodeFactory.java @@ -79,6 +79,7 @@ import com.oracle.truffle.sl.nodes.expression.SLLongLiteralNode; import com.oracle.truffle.sl.nodes.expression.SLMulNodeGen; import com.oracle.truffle.sl.nodes.expression.SLParenExpressionNode; +import com.oracle.truffle.sl.nodes.expression.SLPowNodeGen; import com.oracle.truffle.sl.nodes.expression.SLStringLiteralNode; import com.oracle.truffle.sl.nodes.expression.SLSubNodeGen; import com.oracle.truffle.sl.nodes.local.SLReadArgumentNode; @@ -324,6 +325,9 @@ public SLExpressionNode createBinary(Token opToken, SLExpressionNode leftNode, S case "/": result = SLDivNodeGen.create(leftNode, rightNode); break; + case "^": + result = SLPowNodeGen.create(leftNode, rightNode); + break; case "-": result = SLSubNodeGen.create(leftNode, rightNode); break; diff --git a/src/main/java/com/oracle/truffle/sl/parser/Scanner.java b/src/main/java/com/oracle/truffle/sl/parser/Scanner.java index 474778af2..ca039c882 100644 --- a/src/main/java/com/oracle/truffle/sl/parser/Scanner.java +++ b/src/main/java/com/oracle/truffle/sl/parser/Scanner.java @@ -328,8 +328,8 @@ public class Scanner { static final char EOL = '\n'; static final int eofSym = 0; - static final int maxT = 34; - static final int noSym = 34; + static final int maxT = 35; + static final int noSym = 35; public Buffer buffer; // scanner buffer @@ -366,17 +366,18 @@ public class Scanner { start.set(59, 11); start.set(124, 12); start.set(38, 14); - start.set(60, 28); - start.set(62, 29); - start.set(61, 30); + start.set(60, 29); + start.set(62, 30); + start.set(61, 31); start.set(33, 19); start.set(43, 21); start.set(45, 22); start.set(42, 23); start.set(47, 24); - start.set(46, 25); - start.set(91, 26); - start.set(93, 27); + start.set(94, 25); + start.set(46, 26); + start.set(91, 27); + start.set(93, 28); start.set(Buffer.EOF, -1); literals.put("function", new Integer(4)); literals.put("break", new Integer(10)); @@ -597,23 +598,25 @@ Token NextToken() { case 24: {t.kind = 29; break loop;} case 25: - {t.kind = 31; break loop;} + {t.kind = 30; break loop;} case 26: {t.kind = 32; break loop;} case 27: {t.kind = 33; break loop;} case 28: + {t.kind = 34; break loop;} + case 29: recEnd = pos; recKind = 20; if (ch == '=') {AddCh(); state = 16; break;} else {t.kind = 20; break loop;} - case 29: + case 30: recEnd = pos; recKind = 22; if (ch == '=') {AddCh(); state = 17; break;} else {t.kind = 22; break loop;} - case 30: - recEnd = pos; recKind = 30; + case 31: + recEnd = pos; recKind = 31; if (ch == '=') {AddCh(); state = 18; break;} - else {t.kind = 30; break loop;} + else {t.kind = 31; break loop;} } } diff --git a/src/main/java/com/oracle/truffle/sl/parser/SimpleLanguage.atg b/src/main/java/com/oracle/truffle/sl/parser/SimpleLanguage.atg index 5b4fab1ae..890d31cdf 100644 --- a/src/main/java/com/oracle/truffle/sl/parser/SimpleLanguage.atg +++ b/src/main/java/com/oracle/truffle/sl/parser/SimpleLanguage.atg @@ -212,13 +212,21 @@ Term Term = -Factor +Pow { ("*" | "/") (. Token op = t; .) - Factor (. result = factory.createBinary(op, result, right); .) + Pow (. result = factory.createBinary(op, result, right); .) } . +Pow += +Factor +{ + "^" (. Token op = t; .) + Factor (. result = factory.createBinary(op, result, right); .) +} +. Factor = (. result = null; .)