├── .gitignore ├── .travis.yml ├── README.md ├── benchmarks ├── fibonacci.lua └── mandelbrot.lua ├── bin └── luatruffle ├── pom.xml └── src ├── main └── java │ └── org │ └── luatruffle │ └── main │ ├── Main.java │ ├── builtins │ ├── LuaOSClockBuiltin.java │ └── LuaPrintBuiltin.java │ ├── nodes │ ├── LuaBinaryNode.java │ ├── LuaBooleanConstantNode.java │ ├── LuaExpressionNode.java │ ├── LuaFunctionBodyNode.java │ ├── LuaLongConstantNode.java │ ├── LuaNode.java │ ├── LuaObjectConstantNode.java │ ├── LuaRootNode.java │ ├── LuaStatementNode.java │ ├── LuaTypes.java │ ├── LuaUnaryNode.java │ ├── call │ │ ├── LuaAbstractDispatchNode.java │ │ ├── LuaDirectDispatchNode.java │ │ ├── LuaFunctionCall.java │ │ ├── LuaGenericDispatchNode.java │ │ └── LuaUninitializedDispatchNode.java │ ├── expressions │ │ ├── LuaFunctionBody.java │ │ └── LuaFunctionNode.java │ ├── local │ │ ├── LuaReadArgumentNode.java │ │ ├── LuaReadLocalVariableNode.java │ │ └── LuaWriteLocalVariableNode.java │ ├── operations │ │ ├── arithmetic │ │ │ ├── LuaAddNode.java │ │ │ ├── LuaDivisionOperation.java │ │ │ ├── LuaExponentiationNode.java │ │ │ ├── LuaMultiplicationNode.java │ │ │ ├── LuaNegateNode.java │ │ │ └── LuaSubtractionNode.java │ │ └── relational │ │ │ ├── LuaEqualsNode.java │ │ │ ├── LuaGreaterOrEqualsNode.java │ │ │ ├── LuaGreaterThanNode.java │ │ │ ├── LuaLessOrEqualsNode.java │ │ │ └── LuaLessThanNode.java │ └── statements │ │ ├── LuaBlockNode.java │ │ ├── LuaBreakNode.java │ │ ├── LuaIfNode.java │ │ ├── LuaNopNode.java │ │ ├── LuaReturnNode.java │ │ ├── LuaWhileDoNode.java │ │ └── controlflow │ │ ├── LuaBreakException.java │ │ └── LuaReturnException.java │ ├── runtime │ ├── LuaContext.java │ ├── LuaFunction.java │ ├── LuaFunctionRegistry.java │ └── LuaNull.java │ └── translator │ └── Translator.java └── test ├── java └── org │ └── luatruffle │ └── main │ └── translator │ ├── ArithmeticOperatorsTest.java │ ├── BaseTranslatorTest.java │ ├── MethodDefinitionTest.java │ ├── RelationalOperators.java │ ├── TranslatorTest.java │ ├── ValueTypesTest.java │ └── VariablesTest.java └── resources ├── fibonacci.lua ├── functions.lua ├── ifthenelse.lua ├── numeric_for.lua ├── numeric_for2.lua ├── numeric_for3.lua └── numeric_for_dynamic.lua /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | *.iml 3 | target/* 4 | *.class 5 | .classpath 6 | .project 7 | .settings 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | - oraclejdk7 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LuaTruffle - A Java implementation of the Lua language using Truffle 2 | 3 | Master: [![Build Status](https://travis-ci.org/lucasallan/LuaTruffle.svg?branch=master)](https://travis-ci.org/lucasallan/LuaTruffle) 4 | 5 | ## Compiling 6 | 7 | mvn package 8 | 9 | ## Running 10 | 11 | bin/luatruffle my.lua 12 | 13 | ## Running With Graal 14 | 15 | Download one of: 16 | 17 | * http://lafo.ssw.uni-linz.ac.at/graalvm/openjdk-8-graalvm-b132-linux-x86_64-0.5.tar.gz 18 | * http://lafo.ssw.uni-linz.ac.at/graalvm/openjdk-8-graalvm-b132-macosx-x86_64-0.5.tar.gz 19 | 20 | Then run: 21 | 22 | JAVACMD=../graalvm-jdk1.8.0/bin/java bin/luatruffle my.lua 23 | 24 | ## Options 25 | 26 | To pass options to the JVM, prefix with `-J`. For example, `-J-Xmx1G`. 27 | 28 | ## Performance 29 | 30 | Fibonacci is of course a terrible benchmark, but it's all we can run at the 31 | moment. We also probably don't implement Lua correctly yet. 32 | 33 | Compare: 34 | 35 | lua src/test/resources/fibonacci.lua 36 | luajit src/test/resources/fibonacci.lua 37 | JAVACMD=../graalvm-jdk1.8.0/bin/java bin/luatruffle src/test/resources/fibonacci.lua 38 | 39 | We're around 6x compared to `lua`, and a third as fast as `luajit`. 40 | -------------------------------------------------------------------------------- /benchmarks/fibonacci.lua: -------------------------------------------------------------------------------- 1 | function fibonacci(n) 2 | if n < 2 then 3 | return n 4 | end 5 | return fibonacci(n-1) + fibonacci(n-2) 6 | end 7 | 8 | while true do 9 | local start = os.clock() 10 | print(fibonacci(40)) 11 | print(os.clock() - start) 12 | end 13 | -------------------------------------------------------------------------------- /benchmarks/mandelbrot.lua: -------------------------------------------------------------------------------- 1 | -- The Computer Language Shootout 2 | -- http://shootout.alioth.debian.org/ 3 | -- contributed by Mike Pall 4 | 5 | function mandelbro(width) 6 | local height, wscale = width, 2/width 7 | local m, limit2 = 50, 4.0 8 | local iter = 0 9 | 10 | for y=0,height-1 do 11 | local Ci = 2*y / height - 1 12 | for xb=0,width-1,8 do 13 | local bits = 0 14 | local xbb = xb+7 15 | local loopend 16 | if xbb < width then loopend = xbb else loopend = width - 1 end 17 | for x=xb,loopend do 18 | bits = bits + bits 19 | local Zr, Zi, Zrq, Ziq = 0.0, 0.0, 0.0, 0.0 20 | local Cr = x * wscale - 1.5 21 | for i=1,m do 22 | local Zri = Zr*Zi 23 | Zr = Zrq - Ziq + Cr 24 | Zi = Zri + Zri + Ci 25 | Zrq = Zr*Zr 26 | Ziq = Zi*Zi 27 | iter = iter + 1 28 | if Zrq + Ziq > limit2 then 29 | bits = bits + 1 30 | break 31 | end 32 | end 33 | end 34 | if xbb >= width then 35 | for x=width,xbb do bits = bits + bits + 1 end 36 | end 37 | end 38 | end 39 | return iter 40 | end 41 | 42 | while true do 43 | local t1 = os.clock() 44 | mandelbro(1000) 45 | print(os.clock()-t1) 46 | end 47 | -------------------------------------------------------------------------------- /bin/luatruffle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | JAVACMD=${JAVACMD:=java} 4 | LUATRUFFLE_JAR=${LUATRUFFLE_JAR:=target/luatruffle-complete-0.1-SNAPSHOT.jar} 5 | 6 | PROGRAM_ARGS="" 7 | JAVA_ARGS="" 8 | 9 | for opt in "$@" 10 | do 11 | case $opt in 12 | -J*) 13 | opt=${1:2} 14 | JAVA_ARGS="$JAVA_ARGS $opt" ;; 15 | *) 16 | PROGRAM_ARGS="$PROGRAM_ARGS $opt" ;; 17 | esac 18 | done 19 | 20 | $JAVACMD $JAVA_ARGS -jar $LUATRUFFLE_JAR $PROGRAM_ARGS 21 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.luatruffle 7 | luatruffle 8 | 0.1-SNAPSHOT 9 | 10 | 11 | 12 | 13 | true 14 | 15 | 16 | false 17 | 18 | truffle 19 | http://lafo.ssw.uni-linz.ac.at/nexus/content/repositories/releases/ 20 | 21 | 22 | 23 | 24 | 25 | org.luaj 26 | luaj-jse 27 | 3.0 28 | 29 | 30 | com.oracle 31 | truffle 32 | 0.6 33 | 34 | 35 | com.oracle 36 | truffle-dsl-processor 37 | 0.6 38 | provided 39 | 40 | 41 | junit 42 | junit 43 | 4.11 44 | test 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.apache.maven.plugins 52 | maven-shade-plugin 53 | 2.3 54 | 55 | 56 | package 57 | 58 | shade 59 | 60 | 61 | ${project.artifactId}-complete-${project.version} 62 | 63 | 64 | org.luatruffle.main.Main 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | maven-compiler-plugin 76 | 3.1 77 | 78 | 1.7 79 | 1.7 80 | 81 | 82 | 83 | anno 84 | process-resources 85 | 86 | compile 87 | 88 | 89 | 90 | com.oracle.truffle.dsl.processor.TruffleProcessor 91 | 92 | target/generated-sources 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/Main.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main; 2 | 3 | import org.luatruffle.main.runtime.LuaContext; 4 | import org.luaj.vm2.ast.Chunk; 5 | import org.luaj.vm2.parser.LuaParser; 6 | 7 | import java.io.FileInputStream; 8 | 9 | /** 10 | * Created by Lucas Allan Amorim on 2014-09-08. 11 | */ 12 | public class Main { 13 | 14 | public static void main(String args[]) { 15 | try { 16 | if (args.length != 1) { 17 | System.err.println("usage: luatruffle file"); 18 | System.exit(1); 19 | } 20 | 21 | final String file = args[0]; 22 | 23 | LuaParser parser = new LuaParser(new FileInputStream(file)); 24 | Chunk chunk = parser.Chunk(); 25 | 26 | new LuaContext().executeMain(chunk); 27 | 28 | } catch (Exception e) { 29 | e.printStackTrace(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/builtins/LuaOSClockBuiltin.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.builtins; 2 | 3 | import com.oracle.truffle.api.dsl.Specialization; 4 | import com.oracle.truffle.api.nodes.NodeInfo; 5 | import org.luatruffle.main.nodes.LuaNode; 6 | 7 | /** 8 | * Created by Lucas Allan Amorim on 2014-09-14. 9 | */ 10 | @NodeInfo(shortName = "osclock") 11 | public abstract class LuaOSClockBuiltin extends LuaNode { 12 | 13 | @Specialization 14 | public double osclock() { 15 | return System.nanoTime() / 1e9; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/builtins/LuaPrintBuiltin.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.builtins; 2 | 3 | import com.oracle.truffle.api.CompilerDirectives; 4 | import com.oracle.truffle.api.dsl.NodeChild; 5 | import com.oracle.truffle.api.dsl.Specialization; 6 | import com.oracle.truffle.api.nodes.NodeInfo; 7 | import org.luatruffle.main.nodes.LuaNode; 8 | 9 | /** 10 | * Created by Lucas Allan Amorim on 2014-09-14. 11 | */ 12 | @NodeInfo(shortName = "print") 13 | @NodeChild(value = "value", type = LuaNode.class) 14 | public abstract class LuaPrintBuiltin extends LuaNode { 15 | 16 | @CompilerDirectives.TruffleBoundary 17 | @Specialization 18 | public long print(long value) { 19 | System.out.println(value); 20 | return value; 21 | } 22 | 23 | @CompilerDirectives.TruffleBoundary 24 | @Specialization 25 | public boolean print(boolean value) { 26 | System.out.println(value); 27 | return value; 28 | } 29 | 30 | @CompilerDirectives.TruffleBoundary 31 | @Specialization 32 | public String print(String value) { 33 | System.out.println(value); 34 | return value; 35 | } 36 | 37 | @CompilerDirectives.TruffleBoundary 38 | @Specialization 39 | public Object print(Object value) { 40 | System.out.println(value); 41 | return value; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/LuaBinaryNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes; 2 | 3 | import com.oracle.truffle.api.dsl.NodeChild; 4 | import com.oracle.truffle.api.dsl.NodeChildren; 5 | 6 | /** 7 | * Created by lucas on 2014-09-14. 8 | */ 9 | @NodeChildren({@NodeChild("leftNode"), @NodeChild("rightNode")}) 10 | public abstract class LuaBinaryNode extends LuaExpressionNode { 11 | 12 | protected boolean isEitherString(Object a, Object b) { 13 | return a instanceof String || b instanceof String; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/LuaBooleanConstantNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes; 2 | 3 | import com.oracle.truffle.api.frame.VirtualFrame; 4 | 5 | /** 6 | * Created by Lucas Allan Amorim on 2014-09-11. 7 | */ 8 | public class LuaBooleanConstantNode extends LuaExpressionNode { 9 | 10 | private final boolean value; 11 | 12 | public LuaBooleanConstantNode(boolean value) { 13 | this.value = value; 14 | } 15 | 16 | @Override 17 | public Object execute(VirtualFrame frame) { 18 | return executeBoolean(frame); 19 | } 20 | 21 | @Override 22 | public boolean executeBoolean(VirtualFrame frame) { 23 | return value; 24 | } 25 | 26 | public String toString(){ 27 | return "Constant: " + value; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/LuaExpressionNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes; 2 | 3 | /** 4 | * Created by Lucas Allan Amorim on 2014-09-08. 5 | */ 6 | public abstract class LuaExpressionNode extends LuaNode { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/LuaFunctionBodyNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes; 2 | 3 | import com.oracle.truffle.api.frame.VirtualFrame; 4 | import org.luatruffle.main.nodes.statements.controlflow.LuaReturnException; 5 | import org.luatruffle.main.runtime.LuaNull; 6 | 7 | /** 8 | * Created by Lucas Allan Amorim on 2014-09-10. 9 | */ 10 | public class LuaFunctionBodyNode extends LuaExpressionNode { 11 | 12 | @Child private LuaStatementNode statementNode; 13 | 14 | public LuaFunctionBodyNode(LuaStatementNode statementNode) { 15 | super(); 16 | this.statementNode = statementNode; 17 | } 18 | 19 | @Override 20 | public Object execute(VirtualFrame frame) { 21 | try { 22 | statementNode.executeVoid(frame); 23 | } catch (LuaReturnException ex) { 24 | return ex.result; 25 | } 26 | return LuaNull.SINGLETON; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/LuaLongConstantNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes; 2 | 3 | import com.oracle.truffle.api.frame.VirtualFrame; 4 | 5 | /** 6 | * Created by Lucas Allan Amorim on 2014-09-11. 7 | */ 8 | public class LuaLongConstantNode extends LuaExpressionNode { 9 | 10 | private final long value; 11 | 12 | public LuaLongConstantNode(long value) { 13 | this.value = value; 14 | } 15 | 16 | @Override 17 | public Object execute(VirtualFrame frame) { 18 | return executeLong(frame); 19 | } 20 | 21 | @Override 22 | public long executeLong(VirtualFrame frame) { 23 | return value; 24 | } 25 | 26 | public String toString(){ 27 | return "Constant: " + value; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/LuaNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes; 2 | 3 | import com.oracle.truffle.api.dsl.TypeSystemReference; 4 | import com.oracle.truffle.api.frame.VirtualFrame; 5 | import com.oracle.truffle.api.nodes.Node; 6 | import com.oracle.truffle.api.nodes.UnexpectedResultException; 7 | import org.luatruffle.main.runtime.LuaFunction; 8 | import org.luatruffle.main.runtime.LuaNull; 9 | 10 | import java.math.BigInteger; 11 | 12 | /** 13 | * Created by Lucas Allan Amorim on 2014-09-10. 14 | */ 15 | @TypeSystemReference(LuaTypes.class) 16 | public abstract class LuaNode extends Node { 17 | 18 | public abstract Object execute(VirtualFrame frame); 19 | 20 | public void executeVoid(VirtualFrame frame) { 21 | execute(frame); 22 | } 23 | 24 | public double executeDouble(VirtualFrame frame) throws UnexpectedResultException { 25 | return LuaTypesGen.LUATYPES.expectDouble(execute(frame)); 26 | } 27 | 28 | public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException { 29 | return LuaTypesGen.LUATYPES.expectBoolean(execute(frame)); 30 | } 31 | 32 | public long executeLong(VirtualFrame frame) throws UnexpectedResultException { 33 | return LuaTypesGen.LUATYPES.expectLong(execute(frame)); 34 | } 35 | 36 | public BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException { 37 | return LuaTypesGen.LUATYPES.expectBigInteger(execute(frame)); 38 | } 39 | 40 | public String executeString(VirtualFrame frame) throws UnexpectedResultException { 41 | return LuaTypesGen.LUATYPES.expectString(execute(frame)); 42 | } 43 | 44 | public LuaNull executeLuaNull(VirtualFrame frame) throws UnexpectedResultException { 45 | return LuaTypesGen.LUATYPES.expectLuaNull(execute(frame)); 46 | } 47 | 48 | public LuaFunction executeLuaMethod(VirtualFrame frame) throws UnexpectedResultException { 49 | return LuaTypesGen.LUATYPES.expectLuaFunction(execute(frame)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/LuaObjectConstantNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes; 2 | 3 | import com.oracle.truffle.api.frame.VirtualFrame; 4 | 5 | /** 6 | * Created by Lucas Allan Amorim on 2014-09-11. 7 | */ 8 | public class LuaObjectConstantNode extends LuaExpressionNode { 9 | 10 | private final Object value; 11 | 12 | public LuaObjectConstantNode(Object value) { 13 | this.value = value; 14 | } 15 | 16 | @Override 17 | public Object execute(VirtualFrame frame) { 18 | return value; 19 | } 20 | 21 | public String toString(){ 22 | return "Constant: " + value; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/LuaRootNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes; 2 | 3 | import com.oracle.truffle.api.frame.FrameDescriptor; 4 | import com.oracle.truffle.api.frame.VirtualFrame; 5 | import com.oracle.truffle.api.nodes.RootNode; 6 | 7 | /** 8 | * Created by Lucas Allan Amorim on 2014-09-08. 9 | */ 10 | public class LuaRootNode extends RootNode { 11 | 12 | @Child protected LuaNode body; 13 | 14 | public LuaRootNode(LuaNode body, FrameDescriptor frameDescriptor) { 15 | super(null, frameDescriptor); 16 | this.body = body; 17 | } 18 | 19 | @Override 20 | public Object execute(VirtualFrame frame) { 21 | return body.execute(frame); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/LuaStatementNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes; 2 | 3 | import com.oracle.truffle.api.CompilerAsserts; 4 | import com.oracle.truffle.api.frame.VirtualFrame; 5 | 6 | /** 7 | * Created by Lucas Allan Amorim on 2014-09-08. 8 | */ 9 | public abstract class LuaStatementNode extends LuaNode { 10 | 11 | @Override 12 | public Object execute(VirtualFrame frame) { 13 | final String message = "Statements never return results"; 14 | CompilerAsserts.neverPartOfCompilation(message); 15 | throw new UnsupportedOperationException(message); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/LuaTypes.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes; 2 | 3 | import java.math.BigInteger; 4 | 5 | import com.oracle.truffle.api.dsl.*; 6 | import org.luatruffle.main.runtime.LuaFunction; 7 | import org.luatruffle.main.runtime.LuaNull; 8 | 9 | /** 10 | * Created by Lucas Allan Amorim on 2014-09-08. 11 | */ 12 | @TypeSystem({ long.class, BigInteger.class, double.class, boolean.class, String.class, LuaNull.class, LuaFunction.class}) 13 | public abstract class LuaTypes { 14 | 15 | @TypeCheck 16 | public boolean isLuaNull(Object value) { 17 | return value == LuaNull.SINGLETON; 18 | } 19 | 20 | @TypeCast 21 | public LuaNull asLuaNull(Object value) { 22 | assert isLuaNull(value); 23 | return LuaNull.SINGLETON; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/LuaUnaryNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes; 2 | 3 | import com.oracle.truffle.api.dsl.NodeChild; 4 | import com.oracle.truffle.api.dsl.NodeChildren; 5 | 6 | /** 7 | * Created by lucas on 2014-09-14. 8 | */ 9 | @NodeChildren({@NodeChild("childNode")}) 10 | public abstract class LuaUnaryNode extends LuaExpressionNode { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/call/LuaAbstractDispatchNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.call; 2 | 3 | import com.oracle.truffle.api.frame.VirtualFrame; 4 | import com.oracle.truffle.api.nodes.Node; 5 | import org.luatruffle.main.runtime.LuaFunction; 6 | 7 | /** 8 | * Created by Lucas Allan Amorim on 2014-09-21. 9 | */ 10 | public abstract class LuaAbstractDispatchNode extends Node { 11 | 12 | protected static final int INLINE_CACHE_SIZE = 4; 13 | 14 | protected abstract Object executeDispatch(VirtualFrame frame, LuaFunction function, Object[] arguments); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/call/LuaDirectDispatchNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.call; 2 | 3 | import com.oracle.truffle.api.Assumption; 4 | import com.oracle.truffle.api.Truffle; 5 | import com.oracle.truffle.api.frame.VirtualFrame; 6 | import com.oracle.truffle.api.nodes.DirectCallNode; 7 | import com.oracle.truffle.api.nodes.InvalidAssumptionException; 8 | import org.luatruffle.main.runtime.LuaFunction; 9 | 10 | /** 11 | * Created by Lucas Allan Amorim on 2014-09-24. 12 | */ 13 | public final class LuaDirectDispatchNode extends LuaAbstractDispatchNode { 14 | 15 | private final LuaFunction cachedMethod; 16 | @Child private DirectCallNode callCachedTargetNode; 17 | private final Assumption cachedTargetStable; 18 | @Child private LuaAbstractDispatchNode nextNode; 19 | 20 | public LuaDirectDispatchNode(LuaAbstractDispatchNode next, LuaFunction cachedFunction) { 21 | this.cachedMethod = cachedFunction; 22 | this.callCachedTargetNode = Truffle.getRuntime().createDirectCallNode(cachedFunction.getCallTarget()); 23 | this.cachedTargetStable = cachedFunction.getCallTargetStable(); 24 | this.nextNode = next; 25 | } 26 | 27 | @Override 28 | protected Object executeDispatch(VirtualFrame frame, LuaFunction function, Object[] arguments) { 29 | if (this.cachedMethod == function) { 30 | try { 31 | cachedTargetStable.check(); 32 | return callCachedTargetNode.call(frame, arguments); 33 | } catch (InvalidAssumptionException ex) { 34 | replace(nextNode); 35 | } 36 | } 37 | return nextNode.executeDispatch(frame, function, arguments); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/call/LuaFunctionCall.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.call; 2 | 3 | import com.oracle.truffle.api.CompilerAsserts; 4 | import com.oracle.truffle.api.dsl.UnsupportedSpecializationException; 5 | import com.oracle.truffle.api.frame.VirtualFrame; 6 | import com.oracle.truffle.api.nodes.ExplodeLoop; 7 | import com.oracle.truffle.api.nodes.Node; 8 | import com.oracle.truffle.api.nodes.UnexpectedResultException; 9 | import org.luatruffle.main.nodes.LuaExpressionNode; 10 | import org.luatruffle.main.runtime.LuaFunction; 11 | 12 | /** 13 | * Created by Lucas Allan Amorim on 2014-09-18. 14 | */ 15 | public final class LuaFunctionCall extends LuaExpressionNode { 16 | 17 | @Child protected LuaExpressionNode functionNode; 18 | @Children protected final LuaExpressionNode[] argumentNodes; 19 | @Child protected LuaAbstractDispatchNode dispatchNode; 20 | 21 | public LuaFunctionCall(LuaExpressionNode[] argumentNodes, LuaExpressionNode functionNode, LuaAbstractDispatchNode abstractDispatchNode) { 22 | this.argumentNodes = argumentNodes; 23 | this.functionNode = functionNode; 24 | this.dispatchNode = abstractDispatchNode; 25 | } 26 | 27 | @Override 28 | @ExplodeLoop 29 | public Object execute(VirtualFrame frame) { 30 | try { 31 | LuaFunction method = functionNode.executeLuaMethod(frame); 32 | CompilerAsserts.compilationConstant(argumentNodes.length); 33 | 34 | Object[] argumentValues = new Object[argumentNodes.length]; 35 | for (int i = 0; i < argumentNodes.length; i++) { 36 | argumentValues[i] = argumentNodes[i].execute(frame); 37 | } 38 | return dispatchNode.executeDispatch(frame, method, argumentValues); 39 | } catch (UnexpectedResultException ex) { 40 | throw new UnsupportedSpecializationException(this, new Node[]{functionNode}, ex.getResult()); 41 | } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/call/LuaGenericDispatchNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.call; 2 | 3 | import com.oracle.truffle.api.Truffle; 4 | import com.oracle.truffle.api.frame.VirtualFrame; 5 | import com.oracle.truffle.api.nodes.IndirectCallNode; 6 | import org.luatruffle.main.runtime.LuaFunction; 7 | 8 | /** 9 | * Created by Lucas Allan Amorim on 2014-09-24. 10 | */ 11 | public class LuaGenericDispatchNode extends LuaAbstractDispatchNode { 12 | 13 | @Child private IndirectCallNode callNode = Truffle.getRuntime().createIndirectCallNode(); 14 | 15 | @Override 16 | protected Object executeDispatch(VirtualFrame frame, LuaFunction function, Object[] arguments) { 17 | return callNode.call(frame, function.getCallTarget(), arguments); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/call/LuaUninitializedDispatchNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.call; 2 | 3 | import com.oracle.truffle.api.CompilerDirectives; 4 | import com.oracle.truffle.api.frame.VirtualFrame; 5 | import com.oracle.truffle.api.nodes.Node; 6 | import org.luatruffle.main.runtime.LuaFunction; 7 | 8 | /** 9 | * Created by Lucas Allan Amorim on 2014-09-24. 10 | */ 11 | public final class LuaUninitializedDispatchNode extends LuaAbstractDispatchNode { 12 | @Override 13 | protected Object executeDispatch(VirtualFrame frame, LuaFunction function, Object[] arguments) { 14 | CompilerDirectives.transferToInterpreterAndInvalidate(); 15 | 16 | Node cur = this; 17 | int depth = 0; 18 | while (cur.getParent() instanceof LuaAbstractDispatchNode) { 19 | cur = cur.getParent(); 20 | depth++; 21 | } 22 | LuaFunctionCall methodNode = (LuaFunctionCall) cur.getParent(); 23 | 24 | LuaAbstractDispatchNode replacement; 25 | if (function.getCallTarget() == null) { 26 | throw new UnsupportedOperationException("Call of undefined method: " + function.getName()); 27 | 28 | } else if (depth < INLINE_CACHE_SIZE) { 29 | LuaAbstractDispatchNode next = new LuaUninitializedDispatchNode(); 30 | replacement = new LuaDirectDispatchNode(next, function); 31 | replace(replacement); 32 | 33 | } else { 34 | replacement = new LuaGenericDispatchNode(); 35 | methodNode.dispatchNode.replace(replacement); 36 | } 37 | 38 | return replacement.executeDispatch(frame, function, arguments); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/expressions/LuaFunctionBody.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.expressions; 2 | 3 | import com.oracle.truffle.api.frame.VirtualFrame; 4 | import org.luatruffle.main.nodes.LuaExpressionNode; 5 | import org.luatruffle.main.nodes.LuaStatementNode; 6 | import org.luatruffle.main.nodes.statements.controlflow.LuaReturnException; 7 | import org.luatruffle.main.runtime.LuaNull; 8 | 9 | /** 10 | * Created by Lucas Allan Amorim on 2014-09-12. 11 | */ 12 | public class LuaFunctionBody extends LuaExpressionNode{ 13 | 14 | @Child private LuaStatementNode bodyNode; 15 | 16 | public LuaFunctionBody(LuaStatementNode bodyNode) { 17 | this.bodyNode = bodyNode; 18 | } 19 | 20 | @Override 21 | public Object execute(VirtualFrame frame) { 22 | try { 23 | bodyNode.executeVoid(frame); 24 | } catch (LuaReturnException ex) { 25 | return ex.result; 26 | } 27 | 28 | return LuaNull.SINGLETON; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/expressions/LuaFunctionNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.expressions; 2 | 3 | import com.oracle.truffle.api.frame.VirtualFrame; 4 | import org.luatruffle.main.nodes.LuaExpressionNode; 5 | import org.luatruffle.main.runtime.LuaFunction; 6 | 7 | /** 8 | * Created by Lucas Allan Amorim on 2014-09-24. 9 | */ 10 | public final class LuaFunctionNode extends LuaExpressionNode { 11 | 12 | private final LuaFunction value; 13 | 14 | public LuaFunctionNode(LuaFunction value) { 15 | this.value = value; 16 | } 17 | 18 | public LuaFunction executeFunction(VirtualFrame frame) { 19 | return (LuaFunction) execute(frame); 20 | } 21 | 22 | public Object executeGeneric(VirtualFrame frame) { 23 | return execute(frame); 24 | } 25 | 26 | @Override 27 | public Object execute(VirtualFrame frame) { 28 | return value; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/local/LuaReadArgumentNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.local; 2 | 3 | import com.oracle.truffle.api.dsl.NodeField; 4 | import com.oracle.truffle.api.frame.FrameSlot; 5 | import com.oracle.truffle.api.frame.VirtualFrame; 6 | import org.luatruffle.main.nodes.LuaExpressionNode; 7 | import org.luatruffle.main.runtime.LuaNull; 8 | 9 | /** 10 | * Created by Lucas Allan Amorim on 2014-09-14. 11 | */ 12 | @NodeField(name = "slot", type = FrameSlot.class) 13 | public class LuaReadArgumentNode extends LuaExpressionNode { 14 | 15 | private final int index; 16 | 17 | public LuaReadArgumentNode(int index) { 18 | this.index = index; 19 | } 20 | 21 | @Override 22 | public Object execute(VirtualFrame frame) { 23 | Object[] args = frame.getArguments(); 24 | if (index < args.length) { 25 | return args[index]; 26 | } else { 27 | return LuaNull.SINGLETON; 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/local/LuaReadLocalVariableNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.local; 2 | 3 | import com.oracle.truffle.api.dsl.NodeField; 4 | import com.oracle.truffle.api.dsl.Specialization; 5 | import com.oracle.truffle.api.frame.FrameSlot; 6 | import com.oracle.truffle.api.frame.FrameSlotTypeException; 7 | import com.oracle.truffle.api.frame.VirtualFrame; 8 | import org.luatruffle.main.nodes.LuaExpressionNode; 9 | 10 | /** 11 | * Created by Lucas Allan Amorim on 2014-09-15. 12 | */ 13 | @NodeField(name = "slot", type = FrameSlot.class) 14 | public abstract class LuaReadLocalVariableNode extends LuaExpressionNode { 15 | 16 | protected abstract FrameSlot getSlot(); 17 | 18 | @Specialization(rewriteOn = FrameSlotTypeException.class) 19 | protected long readLong(VirtualFrame frame) throws FrameSlotTypeException { 20 | return frame.getLong(getSlot()); 21 | } 22 | 23 | @Specialization(rewriteOn = FrameSlotTypeException.class) 24 | protected boolean readBoolean(VirtualFrame frame) throws FrameSlotTypeException { 25 | return frame.getBoolean(getSlot()); 26 | } 27 | 28 | @Specialization(rewriteOn = FrameSlotTypeException.class) 29 | protected Object readObject(VirtualFrame frame) throws FrameSlotTypeException { 30 | return frame.getObject(getSlot()); 31 | } 32 | 33 | @Specialization(contains = {"readLong", "readBoolean", "readObject"}) 34 | protected Object read(VirtualFrame frame) { 35 | return frame.getValue(getSlot()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/local/LuaWriteLocalVariableNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.local; 2 | 3 | import com.oracle.truffle.api.CompilerDirectives; 4 | import com.oracle.truffle.api.dsl.NodeChild; 5 | import com.oracle.truffle.api.dsl.NodeField; 6 | import com.oracle.truffle.api.dsl.Specialization; 7 | import com.oracle.truffle.api.frame.FrameSlot; 8 | import com.oracle.truffle.api.frame.FrameSlotKind; 9 | import com.oracle.truffle.api.frame.VirtualFrame; 10 | import org.luatruffle.main.nodes.LuaExpressionNode; 11 | 12 | /** 13 | * Created by Lucas Allan Amorim on 2014-09-15. 14 | */ 15 | @NodeChild("valueNode") 16 | @NodeField(name = "slot", type = FrameSlot.class) 17 | public abstract class LuaWriteLocalVariableNode extends LuaExpressionNode { 18 | 19 | protected abstract FrameSlot getSlot(); 20 | 21 | @Specialization(guards = "isLongKind") 22 | protected long writeLong(VirtualFrame frame, long value) { 23 | frame.setLong(getSlot(), value); 24 | return value; 25 | } 26 | 27 | @Specialization(guards = "isBooleanKind") 28 | protected boolean writeBoolean(VirtualFrame frame, boolean value) { 29 | frame.setBoolean(getSlot(), value); 30 | return value; 31 | } 32 | 33 | @Specialization 34 | protected Object writeObject(VirtualFrame frame, Object value) { 35 | frame.setObject(getSlot(), value); 36 | return value; 37 | } 38 | 39 | protected boolean isLongKind() { 40 | return isKind(FrameSlotKind.Long); 41 | } 42 | 43 | protected boolean isBooleanKind() { 44 | return isKind(FrameSlotKind.Boolean); 45 | } 46 | 47 | private boolean isKind(FrameSlotKind kind) { 48 | if (getSlot().getKind() == kind) { 49 | return true; 50 | } else if (getSlot().getKind() == FrameSlotKind.Illegal) { 51 | CompilerDirectives.transferToInterpreterAndInvalidate(); 52 | getSlot().setKind(kind); 53 | return true; 54 | } else { 55 | return false; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/operations/arithmetic/LuaAddNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.operations.arithmetic; 2 | 3 | import com.oracle.truffle.api.ExactMath; 4 | import com.oracle.truffle.api.dsl.Specialization; 5 | import org.luatruffle.main.nodes.LuaBinaryNode; 6 | 7 | import java.math.BigInteger; 8 | 9 | /** 10 | * Created by Lucas Allan Amorim on 2014-09-14. 11 | */ 12 | public abstract class LuaAddNode extends LuaBinaryNode { 13 | 14 | @Specialization 15 | protected long add(long left, long right) { 16 | return ExactMath.addExact(left, right); 17 | } 18 | 19 | @Specialization 20 | protected BigInteger add(BigInteger left, BigInteger right) { 21 | return left.add(right); 22 | } 23 | 24 | @Specialization(guards = "isString") 25 | protected String add(Object left, Object right) { 26 | return left.toString() + right.toString(); 27 | } 28 | 29 | protected boolean isString(Object a, Object b) { 30 | return a instanceof String || b instanceof String; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/operations/arithmetic/LuaDivisionOperation.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.operations.arithmetic; 2 | 3 | import com.oracle.truffle.api.dsl.Specialization; 4 | import org.luatruffle.main.nodes.LuaBinaryNode; 5 | 6 | import java.math.BigInteger; 7 | 8 | /** 9 | * Created by Lucas Allan Amorim on 2014-09-15. 10 | */ 11 | public abstract class LuaDivisionOperation extends LuaBinaryNode { 12 | 13 | @Specialization 14 | protected long divide(long left, long right) { 15 | return left / right; 16 | } 17 | 18 | @Specialization 19 | protected BigInteger divide(BigInteger left, BigInteger right) { 20 | return left.divide(right); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/operations/arithmetic/LuaExponentiationNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.operations.arithmetic; 2 | 3 | import com.oracle.truffle.api.dsl.Specialization; 4 | import org.luatruffle.main.nodes.LuaBinaryNode; 5 | 6 | import java.math.BigInteger; 7 | 8 | /** 9 | * Created by Lucas Allan Amorim on 2014-09-15. 10 | */ 11 | public abstract class LuaExponentiationNode extends LuaBinaryNode { 12 | 13 | @Specialization 14 | protected long pow(long left, long right) { 15 | return (long) Math.pow(left, right); 16 | } 17 | 18 | @Specialization 19 | protected BigInteger pow(BigInteger left, BigInteger right) { 20 | return left.pow(right.intValue()); 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/operations/arithmetic/LuaMultiplicationNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.operations.arithmetic; 2 | 3 | import com.oracle.truffle.api.ExactMath; 4 | import com.oracle.truffle.api.dsl.Specialization; 5 | import org.luatruffle.main.nodes.LuaBinaryNode; 6 | 7 | import java.math.BigInteger; 8 | 9 | /** 10 | * Created by Lucas Allan Amorim on 2014-09-15. 11 | */ 12 | public abstract class LuaMultiplicationNode extends LuaBinaryNode { 13 | 14 | @Specialization 15 | protected long multiply(long left, long right) { 16 | return ExactMath.multiplyExact(left, right); 17 | } 18 | 19 | @Specialization 20 | protected BigInteger multiply(BigInteger left, BigInteger right) { 21 | return left.multiply(right); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/operations/arithmetic/LuaNegateNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.operations.arithmetic; 2 | 3 | import com.oracle.truffle.api.ExactMath; 4 | import com.oracle.truffle.api.dsl.Specialization; 5 | import org.luatruffle.main.nodes.LuaBinaryNode; 6 | import org.luatruffle.main.nodes.LuaUnaryNode; 7 | 8 | import java.math.BigInteger; 9 | 10 | /** 11 | * Created by Lucas Allan Amorim on 2014-09-14. 12 | */ 13 | public abstract class LuaNegateNode extends LuaUnaryNode { 14 | 15 | @Specialization 16 | protected long negate(long value) { 17 | return -value; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/operations/arithmetic/LuaSubtractionNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.operations.arithmetic; 2 | 3 | import com.oracle.truffle.api.ExactMath; 4 | import com.oracle.truffle.api.dsl.Specialization; 5 | import org.luatruffle.main.nodes.LuaBinaryNode; 6 | 7 | import java.math.BigInteger; 8 | 9 | /** 10 | * Created by Lucas Allan Amorim on 2014-09-15. 11 | */ 12 | public abstract class LuaSubtractionNode extends LuaBinaryNode { 13 | 14 | @Specialization 15 | protected long subtract(long left, long right) { 16 | return ExactMath.subtractExact(left, right); 17 | } 18 | 19 | @Specialization 20 | protected double subtract(double left, double right) { 21 | return left - right; 22 | } 23 | 24 | @Specialization 25 | protected BigInteger subtract(BigInteger left, BigInteger right) { 26 | return left.subtract(right); 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/operations/relational/LuaEqualsNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.operations.relational; 2 | 3 | import com.oracle.truffle.api.dsl.Specialization; 4 | import org.luatruffle.main.nodes.LuaBinaryNode; 5 | 6 | import java.math.BigInteger; 7 | 8 | /** 9 | * Created by Lucas Allan Amorim on 2014-09-14. 10 | */ 11 | public abstract class LuaEqualsNode extends LuaBinaryNode { 12 | 13 | @Specialization 14 | protected boolean isEquals(long left, long right) { 15 | return left == right; 16 | } 17 | 18 | @Specialization 19 | protected boolean isEquals(BigInteger left, BigInteger right) { 20 | return left.equals(right); 21 | } 22 | 23 | @Specialization(guards = "isEitherString") 24 | protected boolean isEquals(Object left, Object right) { 25 | return left.toString().equals(right.toString()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/operations/relational/LuaGreaterOrEqualsNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.operations.relational; 2 | 3 | import com.oracle.truffle.api.dsl.Specialization; 4 | import org.luatruffle.main.nodes.LuaBinaryNode; 5 | 6 | import java.math.BigInteger; 7 | 8 | /** 9 | * Created by Lucas Allan Amorim on 2014-09-14. 10 | */ 11 | public abstract class LuaGreaterOrEqualsNode extends LuaBinaryNode { 12 | 13 | @Specialization 14 | protected boolean isGreaterOrEquals(long left, long right) { 15 | return left >= right; 16 | } 17 | 18 | @Specialization 19 | protected boolean isGreaterOrEquals(BigInteger left, BigInteger right) { 20 | return left.compareTo(right) >= 0; 21 | } 22 | 23 | @Specialization(guards = "isEitherString") 24 | protected boolean isGreaterOrEquals(Object left, Object right) { 25 | return left.toString().length() >= right.toString().length(); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/operations/relational/LuaGreaterThanNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.operations.relational; 2 | 3 | import com.oracle.truffle.api.dsl.Specialization; 4 | import org.luatruffle.main.nodes.LuaBinaryNode; 5 | 6 | import java.math.BigInteger; 7 | 8 | /** 9 | * Created by Lucas Allan Amorim on 2014-09-14. 10 | */ 11 | public abstract class LuaGreaterThanNode extends LuaBinaryNode { 12 | 13 | @Specialization 14 | protected boolean isGreaterThan(long left, long right) { 15 | return left > right; 16 | } 17 | 18 | @Specialization 19 | protected boolean isGreaterThan(BigInteger left, BigInteger right) { 20 | return left.compareTo(right) == 1; 21 | } 22 | 23 | @Specialization(guards = "isEitherString") 24 | protected boolean isGreaterThan(Object left, Object right) { 25 | return left.toString().length() > right.toString().length(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/operations/relational/LuaLessOrEqualsNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.operations.relational; 2 | 3 | import com.oracle.truffle.api.dsl.Specialization; 4 | import org.luatruffle.main.nodes.LuaBinaryNode; 5 | 6 | import java.math.BigInteger; 7 | 8 | /** 9 | * Created by Lucas Allan Amorim on 2014-09-14. 10 | */ 11 | public abstract class LuaLessOrEqualsNode extends LuaBinaryNode { 12 | 13 | @Specialization 14 | protected boolean isLessOrEquals(long left, long right) { 15 | return left <= right; 16 | } 17 | 18 | @Specialization 19 | protected boolean isLessOrEquals(BigInteger left, BigInteger right) { 20 | return left.compareTo(right) <= 0; 21 | } 22 | 23 | @Specialization(guards = "isEitherString") 24 | protected boolean isLessOrEquals(Object left, Object right) { 25 | return left.toString().length() <= right.toString().length(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/operations/relational/LuaLessThanNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.operations.relational; 2 | 3 | import com.oracle.truffle.api.dsl.Specialization; 4 | import org.luatruffle.main.nodes.LuaBinaryNode; 5 | 6 | import java.math.BigInteger; 7 | 8 | /** 9 | * Created by Lucas Allan Amorim on 2014-09-14. 10 | */ 11 | public abstract class LuaLessThanNode extends LuaBinaryNode { 12 | 13 | @Specialization 14 | protected boolean isLessThan(long left, long right) { 15 | return left < right; 16 | } 17 | 18 | @Specialization 19 | protected boolean isLessThan(BigInteger left, BigInteger right) { 20 | return left.compareTo(right) == -1; 21 | } 22 | 23 | @Specialization(guards = "isEitherString") 24 | protected boolean isLessThan(Object left, Object right) { 25 | return left.toString().length() < right.toString().length(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/statements/LuaBlockNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.statements; 2 | 3 | import com.oracle.truffle.api.frame.VirtualFrame; 4 | import com.oracle.truffle.api.nodes.ExplodeLoop; 5 | import org.luatruffle.main.nodes.LuaNode; 6 | import org.luatruffle.main.nodes.LuaStatementNode; 7 | 8 | /** 9 | * Created by Lucas Allan Amorim on 2014-09-10. 10 | */ 11 | public class LuaBlockNode extends LuaStatementNode { 12 | 13 | @Children private final LuaNode[] bodyNodes; 14 | 15 | public LuaBlockNode(LuaNode[] nodes) { 16 | this.bodyNodes = nodes; 17 | } 18 | 19 | @ExplodeLoop 20 | @Override 21 | public void executeVoid(VirtualFrame frame) { 22 | for (LuaNode node : bodyNodes) { 23 | if (node != null){ 24 | node.executeVoid(frame); 25 | } 26 | } 27 | } 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/statements/LuaBreakNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.statements; 2 | 3 | import com.oracle.truffle.api.frame.VirtualFrame; 4 | import org.luatruffle.main.nodes.LuaStatementNode; 5 | import org.luatruffle.main.nodes.statements.controlflow.LuaBreakException; 6 | 7 | /** 8 | * Created by Lucas Allan Amorim on 15-01-10. 9 | */ 10 | public class LuaBreakNode extends LuaStatementNode { 11 | 12 | @Override 13 | public void executeVoid(VirtualFrame frame) { 14 | throw LuaBreakException.SINGLETON; 15 | } 16 | } -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/statements/LuaIfNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.statements; 2 | 3 | import com.oracle.truffle.api.nodes.UnexpectedResultException; 4 | import org.luatruffle.main.nodes.LuaExpressionNode; 5 | import org.luatruffle.main.nodes.LuaNode; 6 | import org.luatruffle.main.nodes.LuaStatementNode; 7 | 8 | import com.oracle.truffle.api.CompilerDirectives; 9 | import com.oracle.truffle.api.frame.VirtualFrame; 10 | import com.oracle.truffle.api.nodes.NodeInfo; 11 | import com.oracle.truffle.api.utilities.BranchProfile; 12 | 13 | /** 14 | * Created by Lucas Allan Amorim on 2014-09-08. 15 | */ 16 | @NodeInfo(shortName = "if", description = "The node implementing a condional statement") 17 | public class LuaIfNode extends LuaStatementNode { 18 | 19 | @Child 20 | private LuaExpressionNode conditionNode; 21 | @Child 22 | private LuaNode thenPartNode; 23 | @Child 24 | private LuaNode elsePartNode; 25 | 26 | private final BranchProfile thenProfile = BranchProfile.create(); 27 | private final BranchProfile elseProfile = BranchProfile.create(); 28 | 29 | @CompilerDirectives.CompilationFinal 30 | private int thenCount; 31 | @CompilerDirectives.CompilationFinal 32 | private int elseCount; 33 | 34 | public LuaIfNode(LuaExpressionNode conditionNode, 35 | LuaNode thenPartNode, LuaNode elsePartNode) { 36 | this.conditionNode = conditionNode; 37 | this.thenPartNode = thenPartNode; 38 | this.elsePartNode = elsePartNode; 39 | } 40 | 41 | @Override 42 | public void executeVoid(VirtualFrame frame) { 43 | final boolean condition; 44 | 45 | try { 46 | condition = conditionNode.executeBoolean(frame); 47 | } catch (UnexpectedResultException e) { 48 | // TODO 49 | throw new UnsupportedOperationException(e); 50 | } 51 | 52 | if (CompilerDirectives.injectBranchProbability(getBranchProbability(), condition)) { 53 | if (CompilerDirectives.inInterpreter()) { 54 | thenCount++; 55 | } 56 | thenProfile.enter(); 57 | thenPartNode.executeVoid(frame); 58 | } else { 59 | if (CompilerDirectives.inInterpreter()) { 60 | elseCount++; 61 | } 62 | elseProfile.enter(); 63 | elsePartNode.executeVoid(frame); 64 | } 65 | 66 | } 67 | 68 | private double getBranchProbability() { 69 | final int totalCount = thenCount + elseCount; 70 | 71 | if (totalCount == 0) { 72 | return 0; 73 | } else { 74 | return (double) thenCount / (double) (thenCount + elseCount); 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/statements/LuaNopNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.statements; 2 | 3 | import com.oracle.truffle.api.frame.VirtualFrame; 4 | import org.luatruffle.main.nodes.LuaStatementNode; 5 | 6 | /** 7 | * Created by chrisseaton on 18/09/2014. 8 | */ 9 | public class LuaNopNode extends LuaStatementNode { 10 | 11 | @Override 12 | public void executeVoid(VirtualFrame frame) { 13 | 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/statements/LuaReturnNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.statements; 2 | 3 | import com.oracle.truffle.api.frame.VirtualFrame; 4 | import org.luatruffle.main.nodes.LuaNode; 5 | import org.luatruffle.main.nodes.LuaStatementNode; 6 | import org.luatruffle.main.nodes.statements.controlflow.LuaReturnException; 7 | 8 | /** 9 | * Created by Lucas Allan Amorim on 2014-09-10. 10 | */ 11 | public class LuaReturnNode extends LuaStatementNode { 12 | 13 | @Child 14 | private LuaNode valueNode; 15 | 16 | public LuaReturnNode(LuaNode valueNode) { 17 | this.valueNode = valueNode; 18 | } 19 | 20 | @Override 21 | public void executeVoid(VirtualFrame frame) { 22 | Object value = valueNode.execute(frame); 23 | throw new LuaReturnException(value); 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/statements/LuaWhileDoNode.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.statements; 2 | 3 | import com.oracle.truffle.api.Truffle; 4 | import com.oracle.truffle.api.frame.VirtualFrame; 5 | import com.oracle.truffle.api.nodes.*; 6 | import org.luatruffle.main.nodes.LuaExpressionNode; 7 | import org.luatruffle.main.nodes.LuaNode; 8 | import org.luatruffle.main.nodes.LuaStatementNode; 9 | import org.luatruffle.main.nodes.statements.controlflow.LuaBreakException; 10 | 11 | /** 12 | * Created by Lucas Allan Amorim on 2014-09-15. 13 | */ 14 | @NodeInfo(shortName = "while") 15 | public class LuaWhileDoNode extends LuaStatementNode { 16 | 17 | @Child protected LoopNode loopNode; 18 | 19 | public LuaWhileDoNode(LuaExpressionNode conditionNode, LuaNode blockNode) { 20 | loopNode = Truffle.getRuntime().createLoopNode(new RepeatingWhileNode(conditionNode, blockNode)); 21 | } 22 | 23 | @Override 24 | public void executeVoid(VirtualFrame frame) { 25 | try { 26 | loopNode.executeLoop(frame); 27 | } catch (LuaBreakException e) { 28 | } 29 | } 30 | 31 | private static class RepeatingWhileNode extends Node implements RepeatingNode { 32 | 33 | @Child private LuaExpressionNode conditionNode; 34 | @Child private LuaNode blockNode; 35 | 36 | public RepeatingWhileNode(LuaExpressionNode conditionNode, LuaNode blockNode) { 37 | this.conditionNode = conditionNode; 38 | this.blockNode = blockNode; 39 | } 40 | 41 | @Override 42 | public boolean executeRepeating(VirtualFrame frame) { 43 | try { 44 | if (!conditionNode.executeBoolean(frame)) { 45 | return false; 46 | } 47 | } catch (UnexpectedResultException e) { 48 | throw new UnsupportedOperationException(e); 49 | } 50 | 51 | blockNode.executeVoid(frame); 52 | 53 | return true; 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/statements/controlflow/LuaBreakException.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.statements.controlflow; 2 | 3 | import com.oracle.truffle.api.nodes.ControlFlowException; 4 | 5 | /** 6 | * Created by Lucas Allan Amorim on 2014-09-15. 7 | */ 8 | public class LuaBreakException extends ControlFlowException { 9 | 10 | public static final LuaBreakException SINGLETON = new LuaBreakException(); 11 | 12 | private LuaBreakException() {} 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/nodes/statements/controlflow/LuaReturnException.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.nodes.statements.controlflow; 2 | 3 | import com.oracle.truffle.api.nodes.ControlFlowException; 4 | 5 | /** 6 | * Created by Lucas Allan Amorim on 2014-09-10. 7 | */ 8 | public class LuaReturnException extends ControlFlowException{ 9 | public final Object result; 10 | 11 | public LuaReturnException(Object result) { 12 | super(); 13 | this.result = result; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/runtime/LuaContext.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.runtime; 2 | 3 | import com.oracle.truffle.api.CallTarget; 4 | import com.oracle.truffle.api.ExecutionContext; 5 | import com.oracle.truffle.api.Truffle; 6 | import com.oracle.truffle.api.dsl.NodeFactory; 7 | import com.oracle.truffle.api.nodes.NodeInfo; 8 | import org.luatruffle.main.builtins.LuaPrintBuiltinFactory; 9 | import org.luatruffle.main.builtins.LuaOSClockBuiltinFactory; 10 | import org.luatruffle.main.nodes.LuaNode; 11 | import org.luatruffle.main.nodes.LuaRootNode; 12 | import org.luatruffle.main.nodes.LuaStatementNode; 13 | import org.luatruffle.main.nodes.expressions.LuaFunctionBody; 14 | import org.luatruffle.main.nodes.local.LuaReadArgumentNode; 15 | import org.luatruffle.main.translator.Translator; 16 | import org.luaj.vm2.ast.Chunk; 17 | 18 | import java.io.PrintStream; 19 | 20 | /** 21 | * Created by Lucas Allan Amorim on 2014-09-14. 22 | */ 23 | public class LuaContext extends ExecutionContext { 24 | 25 | private final LuaFunctionRegistry luaFunctionRegistry; 26 | private final LuaFunctionRegistry luaGlobalVariableRegistry; 27 | 28 | public LuaContext() { 29 | this.luaFunctionRegistry = new LuaFunctionRegistry(); 30 | this.luaGlobalVariableRegistry = new LuaFunctionRegistry(); 31 | installBuiltins(); 32 | } 33 | 34 | public LuaFunction findLuaMethod(String name){ 35 | return luaFunctionRegistry.lookup(name); 36 | } 37 | public LuaFunction findVariable(String name){ 38 | return luaGlobalVariableRegistry.lookup(name); 39 | } 40 | 41 | public void addLuaFunction(String name, LuaRootNode node) { 42 | luaFunctionRegistry.register(name, node); 43 | } 44 | 45 | public void addGlobalVariable(String name, LuaRootNode node) { 46 | luaGlobalVariableRegistry.register(name, node); 47 | } 48 | 49 | public PrintStream getOutput() { 50 | return System.out; 51 | } 52 | 53 | private void installBuiltins() { 54 | installBuiltin(LuaPrintBuiltinFactory.getInstance()); 55 | installBuiltin(LuaOSClockBuiltinFactory.getInstance()); 56 | } 57 | 58 | public void installBuiltin(NodeFactory factory) { 59 | int argumentCount = factory.getExecutionSignature().size(); 60 | Object[] argumentNodes = new Object[argumentCount]; 61 | for (int i = 0; i < argumentCount; i++) { 62 | argumentNodes[i] = new LuaReadArgumentNode(i); 63 | } 64 | for (int i = 0; i < argumentCount; i++) { 65 | argumentNodes[i] = new LuaReadArgumentNode(i); 66 | } 67 | 68 | LuaNode builtinBodyNode = factory.createNode(argumentNodes); 69 | String name = builtinBodyNode.getClass().getAnnotation(NodeInfo.class).shortName(); 70 | 71 | LuaRootNode rootNode = new LuaRootNode(builtinBodyNode, null); 72 | 73 | luaFunctionRegistry.register(name, rootNode); 74 | } 75 | 76 | @Override 77 | public String getLanguageShortName() { 78 | return "Lua"; 79 | } 80 | 81 | public void executeMain(Chunk chunk) { 82 | final Translator translator = new Translator(this); 83 | LuaStatementNode statement = (LuaStatementNode) translator.translate(chunk.block); 84 | LuaFunctionBody body = new LuaFunctionBody(statement); 85 | LuaRootNode root = new LuaRootNode(body, translator.getFrameDescriptor()); 86 | CallTarget callTarget = Truffle.getRuntime().createCallTarget(root); 87 | 88 | callTarget.call(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/runtime/LuaFunction.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.runtime; 2 | 3 | import com.oracle.truffle.api.Assumption; 4 | import com.oracle.truffle.api.RootCallTarget; 5 | import com.oracle.truffle.api.utilities.CyclicAssumption; 6 | 7 | /** 8 | * Created by Lucas Allan Amorim on 2014-09-10. 9 | */ 10 | public final class LuaFunction { 11 | 12 | private final String name; 13 | 14 | 15 | private RootCallTarget callTarget; 16 | 17 | private final CyclicAssumption callTargetStable; 18 | 19 | protected LuaFunction(String name) { 20 | this.name = name; 21 | this.callTargetStable = new CyclicAssumption(name); 22 | } 23 | 24 | public String getName() { 25 | return name; 26 | } 27 | 28 | protected void setCallTarget(RootCallTarget callTarget) { 29 | this.callTarget = callTarget; 30 | callTargetStable.invalidate(); 31 | } 32 | 33 | public RootCallTarget getCallTarget() { 34 | return callTarget; 35 | } 36 | 37 | public Assumption getCallTargetStable() { 38 | return callTargetStable.getAssumption(); 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return name; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/runtime/LuaFunctionRegistry.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.runtime; 2 | 3 | import com.oracle.truffle.api.CompilerAsserts; 4 | import com.oracle.truffle.api.RootCallTarget; 5 | import com.oracle.truffle.api.Truffle; 6 | import org.luatruffle.main.nodes.LuaRootNode; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * Created by Lucas Allan Amorim on 2014-09-14. 13 | */ 14 | public final class LuaFunctionRegistry { 15 | 16 | private final Map methods = new HashMap<>(); 17 | 18 | public LuaFunction lookup(String name) { 19 | CompilerAsserts.neverPartOfCompilation(); 20 | 21 | LuaFunction result = methods.get(name); 22 | if (result == null) { 23 | result = new LuaFunction(name); 24 | methods.put(name, result); 25 | } 26 | return result; 27 | } 28 | 29 | public void register(String name, LuaRootNode rootNode, String[] params) { 30 | CompilerAsserts.neverPartOfCompilation(); 31 | 32 | LuaFunction method = lookup(name); 33 | RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); 34 | method.setCallTarget(callTarget); 35 | } 36 | 37 | public void register(String name, LuaRootNode rootNode) { 38 | CompilerAsserts.neverPartOfCompilation(); 39 | 40 | LuaFunction method = lookup(name); 41 | RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); 42 | method.setCallTarget(callTarget); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/runtime/LuaNull.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.runtime; 2 | 3 | /** 4 | * Created by Lucas Allan Amorim on 2014-09-10. 5 | */ 6 | public final class LuaNull { 7 | public static final LuaNull SINGLETON = new LuaNull(); 8 | 9 | private LuaNull() {} 10 | 11 | @Override 12 | public String toString() { 13 | return "nil"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/luatruffle/main/translator/Translator.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.translator; 2 | 3 | import com.oracle.truffle.api.frame.FrameDescriptor; 4 | import com.oracle.truffle.api.frame.FrameSlot; 5 | import org.luatruffle.main.nodes.*; 6 | import org.luatruffle.main.nodes.call.LuaFunctionCall; 7 | import org.luatruffle.main.nodes.call.LuaUninitializedDispatchNode; 8 | import org.luatruffle.main.nodes.expressions.LuaFunctionBody; 9 | import org.luatruffle.main.nodes.expressions.LuaFunctionNode; 10 | import org.luatruffle.main.nodes.local.LuaReadArgumentNode; 11 | import org.luatruffle.main.nodes.local.LuaReadLocalVariableNodeFactory; 12 | import org.luatruffle.main.nodes.local.LuaWriteLocalVariableNode; 13 | import org.luatruffle.main.nodes.local.LuaWriteLocalVariableNodeFactory; 14 | import org.luatruffle.main.nodes.operations.arithmetic.*; 15 | import org.luatruffle.main.nodes.operations.relational.*; 16 | import org.luatruffle.main.nodes.statements.*; 17 | import org.luatruffle.main.runtime.LuaContext; 18 | import org.luatruffle.main.runtime.LuaFunction; 19 | import org.luatruffle.main.runtime.LuaNull; 20 | import org.luaj.vm2.ast.*; 21 | import org.luaj.vm2.ast.Stat.LocalAssign; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | /** 27 | * Created by Lucas Allan Amorim on 2014-09-08. 28 | */ 29 | 30 | public class Translator extends Visitor { 31 | 32 | private FrameDescriptor frameDescriptor; 33 | private LuaContext context; 34 | private Object rootNode; 35 | 36 | public Translator(LuaContext context) { 37 | frameDescriptor = new FrameDescriptor(); 38 | this.context = context; 39 | } 40 | 41 | // TODO needs a good cleaup 42 | public Object translate(Object object) { 43 | try { 44 | if (object instanceof Chunk) { 45 | return visitChunk((Chunk) object); 46 | } else if (object instanceof Block) { 47 | return visitBlock((Block) object); 48 | } else if (object instanceof Stat.IfThenElse) { 49 | return visitIfThenElse((Stat.IfThenElse) object); 50 | } else if (object instanceof Exp.BinopExp) { 51 | return visitBinoExp((Exp.BinopExp) object); 52 | } else if (object instanceof Stat.Return) { 53 | return visitReturn((Stat.Return) object); 54 | } else if (object instanceof Exp.Constant) { 55 | return visitConstant((Exp.Constant) object); 56 | } else if (object instanceof Stat.FuncDef) { 57 | return visitFuncDef((Stat.FuncDef) object); 58 | } else if (object instanceof Stat.FuncCallStat) { 59 | return visitFuncCallStat((Stat.FuncCallStat) object); 60 | } else if (object instanceof Exp.ParensExp) { 61 | return visitParensExp((Exp.ParensExp) object); 62 | } else if (object instanceof Stat.WhileDo) { 63 | return visitWhileDo((Stat.WhileDo) object); 64 | } else if (object instanceof Stat.LocalAssign) { 65 | return visitLocalAssign((Stat.LocalAssign) object); 66 | } else if (object instanceof Exp.NameExp) { 67 | return visitLocalNameExp((Exp.NameExp) object); 68 | } else if (object instanceof Exp.FuncCall) { 69 | return visitFuncCall((Exp.FuncCall) object); 70 | } else if (object instanceof Stat.LocalFuncDef) { 71 | return visitLocalFuncDef((Stat.LocalFuncDef) object); 72 | } else if (object instanceof Stat.NumericFor) { 73 | return visitNumericFor((Stat.NumericFor) object); 74 | } else if (object instanceof Exp.UnopExp) { 75 | return visitUnopExp((Exp.UnopExp) object); 76 | } else if (object instanceof Stat.Assign) { 77 | return visitAssign((Stat.Assign) object); 78 | } else if (object instanceof Long) { 79 | return new LuaLongConstantNode((Long) object); 80 | } else if (object instanceof Stat.Break) { 81 | return new LuaBreakNode(); 82 | } else if (object instanceof Stat.GenericFor) { 83 | return visitGenericFor((Stat.GenericFor) object); 84 | } 85 | else { 86 | if (object != null) { 87 | System.err.println("Needs be handled: " + object.getClass().getName()); 88 | } 89 | return rootNode; 90 | } 91 | } catch (Exception e) { 92 | if (object instanceof Exp) { 93 | System.out.println("Error line: " + ((Exp) object).beginLine + " Column: " + ((Exp) object).beginColumn ); 94 | } else if (object instanceof Stat) { 95 | System.out.println("Error line: " + ((Stat) object).beginLine + " Column: " + ((Stat) object).beginColumn ); 96 | } 97 | 98 | e.printStackTrace(); 99 | return null; 100 | } 101 | } 102 | 103 | private Object visitGenericFor(Stat.GenericFor genericFor) { 104 | System.out.printf("No support for GenericFor yet. Line: " + genericFor.beginLine); 105 | return new LuaBlockNode(new LuaNode[0]); 106 | } 107 | 108 | private Object visitAssign(Stat.Assign assign) { 109 | final List assignments = new ArrayList<>(); 110 | 111 | for(int i = 0; i< assign.vars.size(); i++) { 112 | LuaExpressionNode luaExpressionNode = (LuaExpressionNode) translate(assign.exps.get(i)); 113 | Exp.NameExp name = (Exp.NameExp) assign.vars.get(i); 114 | assignments.add(declareGlobalVariable(name.name.name, luaExpressionNode)); 115 | //System.out.printf("No support to global variables yet - '%s' declared as a local variable.\n", name.name.name); 116 | } 117 | 118 | if (assignments.size() == 1) { 119 | return assignments.get(0); 120 | } else { 121 | return new LuaBlockNode(assignments.toArray(new LuaNode[assignments.size()])); 122 | } 123 | } 124 | 125 | private Object visitUnopExp(Exp.UnopExp unoExp) { 126 | LuaExpressionNode child = (LuaExpressionNode) translate( unoExp.rhs); 127 | 128 | switch (unoExp.op) { 129 | case 19: 130 | return LuaNegateNodeFactory.create(child); 131 | } 132 | throw new UnsupportedOperationException(String.valueOf(unoExp.op)); 133 | } 134 | 135 | private Object visitNumericFor(Stat.NumericFor numericFor) { 136 | /* 137 | * Desugar from this: 138 | * 139 | * for loopVariable = initial, step, limit 140 | * block 141 | * end 142 | * 143 | * to this: 144 | * 145 | * loopVariable = initial 146 | * while loopVariable <= limit 147 | * block 148 | * loopVariable += step 149 | * end 150 | */ 151 | 152 | final FrameSlot loopVariableFrameSlot = frameDescriptor.findOrAddFrameSlot(numericFor.name.name); 153 | 154 | final LuaExpressionNode translatedStep; 155 | 156 | if (numericFor.step == null) { 157 | translatedStep = new LuaLongConstantNode(1); 158 | } else { 159 | translatedStep = (LuaExpressionNode) translate(numericFor.step); 160 | } 161 | 162 | return new LuaBlockNode(new LuaNode[]{ 163 | LuaWriteLocalVariableNodeFactory.create((LuaExpressionNode) translate(numericFor.initial), loopVariableFrameSlot), 164 | new LuaWhileDoNode( 165 | LuaLessOrEqualsNodeFactory.create( 166 | LuaReadLocalVariableNodeFactory.create(loopVariableFrameSlot), 167 | (LuaExpressionNode) translate(numericFor.limit)), 168 | new LuaBlockNode(new LuaNode[]{ 169 | (LuaNode) translate(numericFor.block), 170 | LuaWriteLocalVariableNodeFactory.create( 171 | LuaAddNodeFactory.create( 172 | LuaReadLocalVariableNodeFactory.create(loopVariableFrameSlot), 173 | translatedStep), 174 | loopVariableFrameSlot) 175 | }) 176 | ) 177 | }); 178 | } 179 | 180 | private Object visitLocalFuncDef(Stat.LocalFuncDef localFuncDef) { 181 | final LuaWriteLocalVariableNode[] paramsIntoLocals = new LuaWriteLocalVariableNode[localFuncDef.body.parlist.names.size()]; 182 | for(int i = 0; i < localFuncDef.body.parlist.names.size(); i++) { 183 | Name paramName = (Name) localFuncDef.body.parlist.names.get(i); 184 | paramsIntoLocals[i] = addFormalParameter(paramName.name, i); 185 | } 186 | LuaBlockNode prelude = new LuaBlockNode(paramsIntoLocals); 187 | LuaStatementNode body = (LuaStatementNode) translate(localFuncDef.body.block); 188 | LuaBlockNode preludeAndBody = new LuaBlockNode(new LuaNode[]{prelude, body}); 189 | LuaFunctionBody methodBody = new LuaFunctionBody(preludeAndBody); 190 | String name = localFuncDef.name.name; 191 | LuaRootNode root = new LuaRootNode(methodBody, getFrameDescriptor()); 192 | context.addLuaFunction(name, root); 193 | System.out.printf("No support to local methods yet - using global methods.\n"); 194 | return root; 195 | } 196 | 197 | private Object visitLocalNameExp(Exp.NameExp nameExp) { 198 | Object name = visitName(nameExp.name); 199 | if (name == null) { 200 | throw new RuntimeException(String.format("Name '%s' not found in translator - Line %s column %s", nameExp.name.name, nameExp.beginLine, nameExp.beginColumn)); 201 | } 202 | return name; 203 | } 204 | 205 | private Object visitName(Name name) { 206 | final FrameSlot frameSlot = frameDescriptor.findFrameSlot(name.name); 207 | if (frameSlot == null) { 208 | return visitGlobalName(name); 209 | } 210 | return LuaReadLocalVariableNodeFactory.create(frameSlot); 211 | } 212 | 213 | private Object visitGlobalName(Name name) { 214 | LuaFunction method = context.findVariable(name.name); 215 | if (method == null) { 216 | return null; 217 | } 218 | return new LuaFunctionCall(new LuaExpressionNode[0], new LuaFunctionNode(method), new LuaUninitializedDispatchNode()); 219 | } 220 | 221 | private Object visitWhileDo(Stat.WhileDo whileDo) { 222 | LuaExpressionNode expression = (LuaExpressionNode) translate(whileDo.exp); 223 | LuaBlockNode whileBlock = (LuaBlockNode) translate(whileDo.block); 224 | return new LuaWhileDoNode(expression, whileBlock); 225 | } 226 | 227 | public Object visitIfThenElse(Stat.IfThenElse ifThenElse) { 228 | 229 | LuaExpressionNode expression = (LuaExpressionNode) translate(ifThenElse.ifexp); 230 | LuaNode ifBlock; 231 | LuaNode elseBlock; 232 | 233 | if (ifThenElse.ifblock != null) { 234 | LuaNode[] ifBlocks = new LuaNode[ifThenElse.ifblock.stats.size()]; 235 | for (int i = 0; i < ifThenElse.ifblock.stats.size(); i++) { 236 | ifBlocks[i] = (LuaNode) translate(ifThenElse.ifblock.stats.get(i)); 237 | } 238 | ifBlock = new LuaBlockNode(ifBlocks); 239 | } else { 240 | ifBlock = new LuaNopNode(); 241 | } 242 | 243 | if (ifThenElse.elseblock != null) { 244 | LuaNode[] elseBlocks = new LuaNode[ifThenElse.elseblock.stats.size()]; 245 | for (int i = 0; i < ifThenElse.elseblock.stats.size(); i++) { 246 | elseBlocks[i] = (LuaNode) translate(ifThenElse.elseblock.stats.get(i)); 247 | } 248 | elseBlock = new LuaBlockNode(elseBlocks); 249 | } else { 250 | elseBlock = new LuaNopNode(); 251 | } 252 | 253 | // TODO Handle elseIfs 254 | return new LuaIfNode(expression, ifBlock, elseBlock); 255 | } 256 | 257 | public LuaNode visitChunk(Chunk chunk) { 258 | return visitBlock(chunk.block); 259 | } 260 | 261 | public LuaNode visitBlock(Block block){ 262 | //visit(block.scope); 263 | LuaNode blockNode; 264 | 265 | if ( block.stats != null ) { 266 | LuaNode blocks[] = new LuaNode[block.stats.size()]; 267 | 268 | for (int i = 0, n = block.stats.size(); i < n; i++) { 269 | Object returnedBlock = translate(block.stats.get(i)); 270 | if (returnedBlock instanceof LuaNode) { 271 | blocks[i] = (LuaNode) returnedBlock; 272 | } 273 | } 274 | 275 | blockNode = new LuaBlockNode(blocks); 276 | } else { 277 | blockNode = new LuaNopNode(); 278 | } 279 | 280 | setRootBlock(blockNode); 281 | return blockNode; 282 | } 283 | 284 | public Object visitFuncDef(Stat.FuncDef funcDef) { 285 | final LuaWriteLocalVariableNode[] paramsIntoLocals = new LuaWriteLocalVariableNode[funcDef.body.parlist.names.size()]; 286 | for(int i = 0; i < funcDef.body.parlist.names.size(); i++) { 287 | Name paramName = (Name) funcDef.body.parlist.names.get(i); 288 | paramsIntoLocals[i] = addFormalParameter(paramName.name, i); 289 | } 290 | LuaBlockNode prelude = new LuaBlockNode(paramsIntoLocals); 291 | LuaStatementNode body = (LuaStatementNode) translate(funcDef.body.block); 292 | LuaBlockNode preludeAndBody = new LuaBlockNode(new LuaNode[]{prelude, body}); 293 | LuaFunctionBody methodBody = new LuaFunctionBody(preludeAndBody); 294 | LuaRootNode root = new LuaRootNode(methodBody, getFrameDescriptor()); 295 | String name = funcDef.name.name.name; 296 | context.addLuaFunction(name, root); 297 | return root; 298 | } 299 | 300 | public LuaWriteLocalVariableNode addFormalParameter(String nameToken, int parameterCount) { 301 | final LuaReadArgumentNode readArg = new LuaReadArgumentNode(parameterCount); 302 | return LuaWriteLocalVariableNodeFactory.create(readArg, getFrameDescriptor().findOrAddFrameSlot(nameToken)); 303 | } 304 | 305 | public Object visitFuncCallStat(Stat.FuncCallStat funcCallStat) { 306 | return visitFuncCall(funcCallStat.funccall); 307 | } 308 | 309 | public Object visitFuncCall(Exp.FuncCall funcCall) { 310 | if (funcCall.isfunccall()) { 311 | // Calling a function 312 | 313 | LuaFunction method; 314 | 315 | if (funcCall.lhs instanceof Exp.NameExp) { 316 | Exp.NameExp nameExp = (Exp.NameExp) funcCall.lhs; 317 | method = context.findLuaMethod(nameExp.name.name); 318 | } else if (funcCall.lhs instanceof Exp.FieldExp) { 319 | Exp.FieldExp fieldExp = (Exp.FieldExp) funcCall.lhs; 320 | 321 | // Hack: statically look for os.clock and use osclock 322 | 323 | if (fieldExp.lhs instanceof Exp.NameExp && ((Exp.NameExp) fieldExp.lhs).name.name.equals("os") && fieldExp.name.name.equals("clock")) { 324 | method = context.findLuaMethod("osclock"); 325 | } else { 326 | throw new UnsupportedOperationException(); 327 | } 328 | } else { 329 | throw new UnsupportedOperationException(); 330 | } 331 | 332 | List arguments = visitFuncArgs(funcCall.args); 333 | return new LuaFunctionCall(arguments.toArray(new LuaExpressionNode[arguments.size()]), new LuaFunctionNode(method), new LuaUninitializedDispatchNode()); 334 | } 335 | throw new UnsupportedOperationException(String.valueOf("FuncCallStat")); 336 | } 337 | 338 | public List visitFuncArgs(FuncArgs funcArgs) { 339 | List params = new ArrayList(); 340 | if (funcArgs.exps != null) { 341 | for (Object object : funcArgs.exps) { 342 | //LuaReadArgumentNode 343 | LuaExpressionNode node = (LuaExpressionNode) translate(object); 344 | params.add(node); 345 | } 346 | } 347 | return params; 348 | } 349 | 350 | public Object visitLocalAssign(LocalAssign localAssign) { 351 | final List assignments = new ArrayList<>(); 352 | 353 | for(int i = 0; i< localAssign.names.size(); i++) { 354 | LuaExpressionNode luaExpressionNode; 355 | if (localAssign.values == null || localAssign.values.get(i) == null) { 356 | luaExpressionNode = new LuaObjectConstantNode(LuaNull.SINGLETON); 357 | } else { 358 | luaExpressionNode = (LuaExpressionNode) translate(localAssign.values.get(i)); 359 | } 360 | String name = ((Name) localAssign.names.get(i)).name; 361 | assignments.add(declareLocalVariable(name, luaExpressionNode)); 362 | } 363 | 364 | if (assignments.size() == 1) { 365 | return assignments.get(0); 366 | } else { 367 | return new LuaBlockNode(assignments.toArray(new LuaNode[assignments.size()])); 368 | } 369 | } 370 | 371 | public LuaReturnNode visitReturn(Stat.Return aReturn) { 372 | //System.out.println(aReturn.nreturns()); //might have more than one return 373 | Object objectReturned = translate(aReturn.values.get(0)); 374 | return new LuaReturnNode((LuaNode) objectReturned); 375 | } 376 | 377 | @Override 378 | public void visit(FuncBody funcBody) { 379 | funcBody.block.accept(this); 380 | funcBody.parlist.accept(this); 381 | } 382 | 383 | public Object visitBinoExp(Exp.BinopExp binopExp) { 384 | LuaExpressionNode left = (LuaExpressionNode) translate( binopExp.lhs); 385 | LuaExpressionNode right = (LuaExpressionNode) translate(binopExp.rhs); 386 | 387 | switch (binopExp.op) { 388 | case 13: 389 | return LuaAddNodeFactory.create(left, right); 390 | case 24: 391 | return LuaEqualsNodeFactory.create(left, right); 392 | case 61: 393 | return LuaEqualsNodeFactory.create(left, right); 394 | case 63: 395 | return LuaGreaterThanNodeFactory.create(left, right); 396 | case 62: 397 | return LuaGreaterOrEqualsNodeFactory.create(left, right); 398 | case 26: 399 | return LuaLessOrEqualsNodeFactory.create(left, right); 400 | case 25: 401 | return LuaLessThanNodeFactory.create(left, right); 402 | case 15: 403 | return LuaMultiplicationNodeFactory.create(left, right); 404 | case 16: 405 | return LuaDivisionOperationFactory.create(left, right); 406 | case 14: 407 | return LuaSubtractionNodeFactory.create(left, right); 408 | case 18: 409 | return LuaExponentiationNodeFactory.create(left, right); 410 | } 411 | throw new UnsupportedOperationException(String.valueOf(binopExp.op)); 412 | } 413 | 414 | public LuaNode visitConstant(Exp.Constant constant){ 415 | if (constant.value.typename().equals("number")){ 416 | return new LuaLongConstantNode(constant.value.checklong()); 417 | } else if (constant.value.typename().equals("nil")) { 418 | return new LuaObjectConstantNode(LuaNull.SINGLETON); 419 | } else if (constant.value.typename().equals("string")){ 420 | return new LuaObjectConstantNode(constant.value.toString()); 421 | } else if (constant.value.typename().equals("boolean")){ 422 | return new LuaBooleanConstantNode(constant.value.checkboolean()); 423 | } 424 | // needs to handle others lua types 425 | throw new UnsupportedOperationException(constant.value.typename()); 426 | } 427 | 428 | public Object visitParensExp(Exp.ParensExp parensExp) { 429 | return translate(parensExp.exp); 430 | } 431 | 432 | public void setRootBlock(Object object) { 433 | if (rootNode == null) { 434 | this.rootNode = object; 435 | } 436 | } 437 | 438 | public FrameDescriptor getFrameDescriptor() { 439 | return frameDescriptor; 440 | } 441 | 442 | private LuaNode declareLocalVariable(String name, LuaExpressionNode value) { 443 | return LuaWriteLocalVariableNodeFactory.create(value, frameDescriptor.findOrAddFrameSlot(name)); 444 | } 445 | 446 | private LuaRootNode declareGlobalVariable(String name, LuaExpressionNode value) { 447 | LuaRootNode root = new LuaRootNode(value, getFrameDescriptor()); 448 | context.addGlobalVariable(name, root); 449 | return root; 450 | } 451 | } 452 | -------------------------------------------------------------------------------- /src/test/java/org/luatruffle/main/translator/ArithmeticOperatorsTest.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.translator; 2 | 3 | import org.junit.Test; 4 | import org.luatruffle.main.translator.BaseTranslatorTest; 5 | 6 | /** 7 | * Created by Lucas Allan Amorim on 2014-09-15. 8 | */ 9 | public class ArithmeticOperatorsTest extends BaseTranslatorTest { 10 | 11 | @Test 12 | public void testAddOperatorsWithNumbers(){ 13 | long expectedResult = 4; 14 | assertEquals(createCallTarget(createTempFile("return 2 + 2")).call(), expectedResult); 15 | } 16 | 17 | @Test 18 | public void testAddOperatorsWithString(){ 19 | assertEquals(createCallTarget(createTempFile("return 'Hello' + ' world'")).call(), "Hello world"); 20 | } 21 | 22 | @Test 23 | public void testMultiplicationOperators(){ 24 | long expectedValue = 8; 25 | assertEquals(createCallTarget(createTempFile("return 2 * 4")).call(), expectedValue); 26 | } 27 | 28 | @Test 29 | public void testDivisionOperators(){ 30 | long expectedValue = 2; 31 | assertEquals(createCallTarget(createTempFile("return 4 / 2")).call(), expectedValue); 32 | } 33 | 34 | @Test 35 | public void testSubtractionOperators(){ 36 | long expectedValue = 2; 37 | assertEquals(createCallTarget(createTempFile("return 4 - 2")).call(), expectedValue); 38 | } 39 | 40 | @Test 41 | public void testExponentiationOperators(){ 42 | long expectedValue = 16; 43 | assertEquals(createCallTarget(createTempFile("return 4 ^ 2")).call(), expectedValue); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/org/luatruffle/main/translator/BaseTranslatorTest.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.translator; 2 | 3 | import com.oracle.truffle.api.CallTarget; 4 | import com.oracle.truffle.api.Truffle; 5 | import junit.framework.TestCase; 6 | import org.luatruffle.main.nodes.LuaRootNode; 7 | import org.luatruffle.main.nodes.LuaStatementNode; 8 | import org.luatruffle.main.nodes.expressions.LuaFunctionBody; 9 | import org.luatruffle.main.runtime.LuaContext; 10 | import org.luaj.vm2.ast.Chunk; 11 | import org.luaj.vm2.parser.LuaParser; 12 | import org.luatruffle.main.translator.Translator; 13 | 14 | import java.io.*; 15 | 16 | /** 17 | * Created by Lucas Allan Amorim on 2014-09-15. 18 | */ 19 | public abstract class BaseTranslatorTest extends TestCase { 20 | 21 | protected CallTarget createCallTarget(String file) { 22 | try { 23 | Translator translator = new Translator(new LuaContext()); 24 | LuaParser parser = new LuaParser(new FileInputStream(file)); 25 | Chunk chunk = parser.Chunk(); 26 | 27 | LuaStatementNode statement = (LuaStatementNode) translator.translate(chunk.block); 28 | LuaFunctionBody body = new LuaFunctionBody(statement); 29 | LuaRootNode root = new LuaRootNode(body, translator.getFrameDescriptor()); 30 | CallTarget callTarget = Truffle.getRuntime().createCallTarget(root); 31 | 32 | return callTarget; 33 | } catch (Exception ex) { 34 | ex.printStackTrace(); 35 | return null; 36 | } 37 | } 38 | 39 | protected String getLuaFile(String file) { 40 | return getClass().getResource("/" + file).getFile(); 41 | } 42 | 43 | protected String createTempFile(String content) { 44 | try { 45 | File temp = File.createTempFile("tmp_file", ".tmp"); 46 | FileWriter fw = new FileWriter(temp.getAbsoluteFile()); 47 | BufferedWriter bw = new BufferedWriter(fw); 48 | bw.write(content); 49 | bw.close(); 50 | return temp.getAbsolutePath(); 51 | } catch (IOException e) { 52 | e.printStackTrace(); 53 | } 54 | return null; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/org/luatruffle/main/translator/MethodDefinitionTest.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.translator; 2 | 3 | import org.junit.Test; 4 | import org.luatruffle.main.runtime.LuaNull; 5 | 6 | /** 7 | * Created by Lucas Allan Amorim on 2014-09-25. 8 | */ 9 | public class MethodDefinitionTest extends BaseTranslatorTest { 10 | @Test 11 | public void testFunctionDefinitionAndCallTest(){ 12 | assertEquals(createCallTarget(createTempFile( 13 | "function newFunction()\n" + 14 | "return 10\n" + 15 | "end\n" + 16 | "return newFunction()") 17 | ).call(), (long) 10); 18 | } 19 | @Test 20 | public void testFunctionsWithParamTest(){ 21 | assertEquals(createCallTarget(createTempFile( 22 | "function return_value(a)\n" + 23 | "return a\n" + 24 | "end\n" + 25 | "return return_value(10)") 26 | ).call(), (long) 10); 27 | } 28 | 29 | public void testDefiningLocalFunctions() { 30 | assertEquals(createCallTarget(createTempFile( 31 | "local function newFunction()\n" + 32 | "return 10\n" + 33 | "end") 34 | ).call(), LuaNull.SINGLETON); 35 | } 36 | 37 | public void testCallingLocalFunctions() { 38 | assertEquals(createCallTarget(createTempFile( 39 | "local function return_value()\n" + 40 | "return 10\n" + 41 | "end\n" + 42 | "return return_value()") 43 | ).call(), (long) 10); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/org/luatruffle/main/translator/RelationalOperators.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.translator; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by Lucas Allan Amorim on 2014-09-15. 7 | */ 8 | public class RelationalOperators extends TranslatorTest { 9 | 10 | @Test 11 | public void testEqualsNode() { 12 | assertEquals(createCallTarget(createTempFile("return 1 == 1")).call(), true); 13 | assertEquals(createCallTarget(createTempFile("return 1 ~= 1")).call(), true); 14 | } 15 | 16 | @Test 17 | public void testGreaterOrEqualsNode(){ 18 | assertEquals(createCallTarget(createTempFile("return 1 >= 1")).call(), true); 19 | assertEquals(createCallTarget(createTempFile("return 2 >= 1")).call(), true); 20 | assertEquals(createCallTarget(createTempFile("return 1 >= 2")).call(), false); 21 | } 22 | 23 | @Test 24 | public void testGreaterThanNode(){ 25 | assertEquals(createCallTarget(createTempFile("return 1 > 1")).call(), false); 26 | assertEquals(createCallTarget(createTempFile("return 2 > 1")).call(), true); 27 | assertEquals(createCallTarget(createTempFile("return 1 > 2")).call(), false); 28 | } 29 | 30 | @Test 31 | public void testLessThanNode(){ 32 | assertEquals(createCallTarget(createTempFile("return 1 < 1")).call(), false); 33 | assertEquals(createCallTarget(createTempFile("return 2 < 1")).call(), false); 34 | assertEquals(createCallTarget(createTempFile("return 1 < 2")).call(), true); 35 | } 36 | 37 | @Test 38 | public void testLessOrEqualsNode(){ 39 | assertEquals(createCallTarget(createTempFile("return 1 <= 1")).call(), true); 40 | assertEquals(createCallTarget(createTempFile("return 2 <= 1")).call(), false); 41 | assertEquals(createCallTarget(createTempFile("return 1 <= 2")).call(), true); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/org/luatruffle/main/translator/TranslatorTest.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.translator; 2 | 3 | import com.oracle.truffle.api.CallTarget; 4 | import org.junit.Test; 5 | /** 6 | * Created by Lucas Allan Amorim on 2014-09-12. 7 | */ 8 | public class TranslatorTest extends BaseTranslatorTest { 9 | 10 | @Test 11 | public void testIfThenElse() { 12 | CallTarget callTarget = createCallTarget(getLuaFile("ifthenelse.lua")); 13 | long expectResult = 10; 14 | assertEquals(callTarget.call(), expectResult); 15 | } 16 | 17 | @Test 18 | public void testNumericFor() { 19 | CallTarget callTarget = createCallTarget(getLuaFile("numeric_for.lua")); 20 | long expectResult = 10; 21 | assertEquals(callTarget.call(), expectResult); 22 | } 23 | 24 | @Test 25 | public void testNumericForWithParam() { 26 | CallTarget callTarget = createCallTarget(getLuaFile("numeric_for2.lua")); 27 | long expectResult = 0; 28 | assertEquals(callTarget.call(), expectResult); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/org/luatruffle/main/translator/ValueTypesTest.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.translator; 2 | 3 | import org.luatruffle.main.runtime.LuaNull; 4 | import org.junit.Test; 5 | 6 | /** 7 | * Created by Lucas Allan Amorim on 2014-09-16. 8 | */ 9 | public class ValueTypesTest extends BaseTranslatorTest { 10 | 11 | @Test 12 | public void testNilValue() { 13 | assertEquals(createCallTarget(createTempFile("return nil")).call(), LuaNull.SINGLETON); 14 | } 15 | 16 | @Test 17 | public void testStringValue() { 18 | assertEquals(createCallTarget(createTempFile("return 'hello'")).call(), "hello"); 19 | } 20 | 21 | @Test 22 | public void testNumericValue() { 23 | assertEquals(createCallTarget(createTempFile("return 12")).call(), (long) 12); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/org/luatruffle/main/translator/VariablesTest.java: -------------------------------------------------------------------------------- 1 | package org.luatruffle.main.translator; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by Lucas Allan Amorim on 2014-09-18. 7 | */ 8 | public class VariablesTest extends BaseTranslatorTest { 9 | 10 | @Test 11 | public void testLocalVariables(){ 12 | assertEquals(createCallTarget(createTempFile("local num = 20\nreturn num")).call(), (long) 20); 13 | } 14 | 15 | @Test 16 | public void testGlobalVariables(){ 17 | assertEquals(createCallTarget(createTempFile("num = 20\nreturn num")).call(), (long) 20); 18 | } 19 | 20 | @Test 21 | public void testMultipleAssignment(){ 22 | assertEquals(createCallTarget(createTempFile("local a, b = 14, 2\nreturn a + b")).call(), (long) 14 + 2); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/test/resources/fibonacci.lua: -------------------------------------------------------------------------------- 1 | function fibonacci(n) 2 | if n < 2 then 3 | return n 4 | end 5 | return fibonacci(n-1) + fibonacci(n-2) 6 | end 7 | 8 | while true do 9 | start = os.clock() 10 | print(fibonacci(40)) 11 | print(os.clock() - start) 12 | end 13 | -------------------------------------------------------------------------------- /src/test/resources/functions.lua: -------------------------------------------------------------------------------- 1 | function newFunction(name) 2 | print(name) 3 | end 4 | return newFunction("hello") -------------------------------------------------------------------------------- /src/test/resources/ifthenelse.lua: -------------------------------------------------------------------------------- 1 | if 1 ~= 0 then 2 | return 0 3 | else 4 | return 10 5 | end 6 | -------------------------------------------------------------------------------- /src/test/resources/numeric_for.lua: -------------------------------------------------------------------------------- 1 | local count = 0 2 | for i=0,9,10 do 3 | local count = count + 10 4 | end 5 | return count -------------------------------------------------------------------------------- /src/test/resources/numeric_for2.lua: -------------------------------------------------------------------------------- 1 | local count = 0 2 | for i=10,1,-1 do 3 | local count = count + 10 4 | end 5 | return count -------------------------------------------------------------------------------- /src/test/resources/numeric_for3.lua: -------------------------------------------------------------------------------- 1 | local count = 1 2 | 3 | for i=0,10 do 4 | count = count + i 5 | end 6 | print(count) -- 56 7 | return count -------------------------------------------------------------------------------- /src/test/resources/numeric_for_dynamic.lua: -------------------------------------------------------------------------------- 1 | local loop_start = 0 2 | local loop_end = 100 3 | local count = 0 4 | for i=loop_start,loop_end do 5 | count = count + 1 6 | end 7 | return count 8 | --------------------------------------------------------------------------------