changeset 31:5cf15507d77e

separate interpreter from interface git-svn-id: https://luan-java.googlecode.com/svn/trunk@32 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Thu, 13 Dec 2012 02:50:04 +0000
parents 8d8f4f5caef4
children c3eab5a3ce3c
files src/luan/CmdLine.java src/luan/LuaClosure.java src/luan/LuaState.java src/luan/interp/AddExpr.java src/luan/interp/AndExpr.java src/luan/interp/Block.java src/luan/interp/BreakStmt.java src/luan/interp/Chunk.java src/luan/interp/ConcatExpr.java src/luan/interp/ConstExpr.java src/luan/interp/DivExpr.java src/luan/interp/EnvExpr.java src/luan/interp/EqExpr.java src/luan/interp/ExpList.java src/luan/interp/Expr.java src/luan/interp/Expressions.java src/luan/interp/ExpressionsExpr.java src/luan/interp/ExpressionsStmt.java src/luan/interp/FnCall.java src/luan/interp/GenericForStmt.java src/luan/interp/GetExpr.java src/luan/interp/GetLocalVar.java src/luan/interp/IfStmt.java src/luan/interp/LeExpr.java src/luan/interp/LenExpr.java src/luan/interp/LtExpr.java src/luan/interp/LuaClosure.java src/luan/interp/LuaCompiler.java src/luan/interp/LuaParser.java src/luan/interp/LuaStateImpl.java src/luan/interp/ModExpr.java src/luan/interp/MulExpr.java src/luan/interp/NotExpr.java src/luan/interp/NumericForStmt.java src/luan/interp/OrExpr.java src/luan/interp/PowExpr.java src/luan/interp/RepeatStmt.java src/luan/interp/ReturnException.java src/luan/interp/ReturnStmt.java src/luan/interp/SetLocalVar.java src/luan/interp/SetStmt.java src/luan/interp/SetTableEntry.java src/luan/interp/Settable.java src/luan/interp/Stmt.java src/luan/interp/SubExpr.java src/luan/interp/TableExpr.java src/luan/interp/UnmExpr.java src/luan/interp/VarArgs.java src/luan/interp/WhileStmt.java
diffstat 49 files changed, 164 insertions(+), 212 deletions(-) [+]
line wrap: on
line diff
--- a/src/luan/CmdLine.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/CmdLine.java	Thu Dec 13 02:50:04 2012 +0000
@@ -4,13 +4,14 @@
 import java.util.Arrays;
 import java.util.Scanner;
 import luan.lib.BasicLib;
+import luan.interp.LuaCompiler;
 
 
 public class CmdLine {
 	static final String version = "Luan 0.0";
 
 	public static void main(String[] args) throws Exception {
-		LuaState lua = new LuaState();
+		LuaState lua = LuaCompiler.newLuaState();
 		BasicLib.register(lua);
 		boolean interactive = false;
 		boolean showVersion = false;
--- a/src/luan/LuaClosure.java	Fri Dec 07 20:22:19 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-package luan;
-
-import luan.interp.Chunk;
-import luan.interp.ReturnException;
-
-
-public final class LuaClosure extends LuaFunction {
-	private final Chunk chunk;
-
-	public LuaClosure(Chunk chunk,LuaState lua) {
-		this.chunk = chunk;
-	}
-
-	public Object[] call(LuaState lua,Object... args) throws LuaException {
-		Chunk chunk = this.chunk;
-		while(true) {
-			Object[] varArgs = null;
-			if( chunk.isVarArg ) {
-				if( args.length > chunk.numArgs ) {
-					varArgs = new Object[ args.length - chunk.numArgs ];
-					for( int i=0; i<varArgs.length; i++ ) {
-						varArgs[i] = args[chunk.numArgs+i];
-					}
-				} else {
-					varArgs = LuaFunction.EMPTY_RTN;
-				}
-			}
-			Object[] stack = lua.newStack(chunk.stackSize,varArgs);
-			final int n = Math.min(args.length,chunk.numArgs);
-			for( int i=0; i<n; i++ ) {
-				stack[i] = args[i];
-			}
-			Object[] returnValues;
-			LuaClosure tailFn;
-			try {
-				chunk.block.eval(lua);
-			} catch(ReturnException e) {
-			} finally {
-				returnValues = lua.returnValues;
-				tailFn = lua.tailFn;
-				lua.popStack();
-			}
-			if( tailFn == null )
-				return returnValues;
-			chunk = tailFn.chunk;
-			args = returnValues;
-		}
-	}
-
-}
--- a/src/luan/LuaState.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/LuaState.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,46 +1,6 @@
 package luan;
 
 
-public class LuaState {
-	private final LuaTable env = new LuaTable();
-
-	public LuaTable env() {
-		return env;
-	}
-
-
-	private static class LuaStack {
-		final LuaStack previousStack;
-		final Object[] a;
-		final Object[] varArgs;
-
-		LuaStack( LuaStack previousStack, int stackSize, Object[] varArgs) {
-			this.previousStack = previousStack;
-			this.a = new Object[stackSize];
-			this.varArgs = varArgs;
-		}
-	}
-
-	private LuaStack stack = null;
-	public Object[] returnValues;
-	public LuaClosure tailFn;
-
-	Object[] newStack(int stackSize, Object[] varArgs) {
-		stack = new LuaStack(stack,stackSize,varArgs);
-		return stack.a;
-	}
-
-	void popStack() {
-		returnValues = LuaFunction.EMPTY_RTN;
-		tailFn = null;
-		stack = stack.previousStack;
-	}
-
-	public Object[] stack() {
-		return stack.a;
-	}
-
-	public Object[] varArgs() {
-		return stack.varArgs;
-	}
+public interface LuaState {
+	public LuaTable env();
 }
--- a/src/luan/interp/AddExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/AddExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -3,7 +3,6 @@
 import luan.Lua;
 import luan.LuaNumber;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class AddExpr extends BinaryOpExpr {
@@ -12,7 +11,7 @@
 		super(op1,op2);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		double n1 = Lua.checkNumber(op1.eval(lua)).value();
 		double n2 = Lua.checkNumber(op2.eval(lua)).value();
 		return new LuaNumber( n1 + n2 );
--- a/src/luan/interp/AndExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/AndExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -2,7 +2,6 @@
 
 import luan.Lua;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class AndExpr extends BinaryOpExpr {
@@ -11,7 +10,7 @@
 		super(op1,op2);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		Object v1 = op1.eval(lua);
 		return !Lua.toBoolean(v1) ? v1 : op2.eval(lua);
 	}
--- a/src/luan/interp/Block.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/Block.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,6 +1,5 @@
 package luan.interp;
 
-import luan.LuaState;
 import luan.LuaException;
 
 
@@ -17,7 +16,7 @@
 		this.stackEnd = stackEnd;
 	}
 
-	@Override public void eval(LuaState lua) throws LuaException {
+	@Override public void eval(LuaStateImpl lua) throws LuaException {
 		try {
 			for( Stmt stmt : stmts ) {
 				stmt.eval(lua);
--- a/src/luan/interp/BreakStmt.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/BreakStmt.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,11 +1,9 @@
 package luan.interp;
 
-import luan.LuaState;
-
 
 final class BreakStmt implements Stmt {
 
-	@Override public void eval(LuaState lua) {
+	@Override public void eval(LuaStateImpl lua) {
 		throw new BreakException();
 	}
 }
--- a/src/luan/interp/Chunk.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/Chunk.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,11 +1,9 @@
 package luan.interp;
 
-import luan.LuaState;
 import luan.LuaException;
-import luan.LuaClosure;
 
 
-public final class Chunk implements Expr {
+final class Chunk implements Expr {
 	public final Stmt block;
 	public final int stackSize;
 	public final int numArgs;
@@ -33,11 +31,11 @@
 		}
 	}
 
-	public LuaClosure newClosure(LuaState lua) {
+	LuaClosure newClosure(LuaStateImpl lua) {
 		return new LuaClosure(this,lua);
 	}
 
-	@Override public Object eval(LuaState lua) {
+	@Override public Object eval(LuaStateImpl lua) {
 		return newClosure(lua);
 	}
 
--- a/src/luan/interp/ConcatExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/ConcatExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -3,7 +3,6 @@
 import luan.Lua;
 import luan.LuaNumber;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class ConcatExpr extends BinaryOpExpr {
@@ -12,7 +11,7 @@
 		super(op1,op2);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		return toString(op1.eval(lua)) + toString(op2.eval(lua));
 	}
 
--- a/src/luan/interp/ConstExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/ConstExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,7 +1,5 @@
 package luan.interp;
 
-import luan.LuaState;
-
 
 final class ConstExpr implements Expr {
 	private final Object obj;
@@ -10,7 +8,7 @@
 		this.obj = obj;
 	}
 
-	@Override public Object eval(LuaState lua) {
+	@Override public Object eval(LuaStateImpl lua) {
 		return obj;
 	}
 }
--- a/src/luan/interp/DivExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/DivExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -3,7 +3,6 @@
 import luan.Lua;
 import luan.LuaNumber;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class DivExpr extends BinaryOpExpr {
@@ -12,7 +11,7 @@
 		super(op1,op2);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		double n1 = Lua.checkNumber(op1.eval(lua)).value();
 		double n2 = Lua.checkNumber(op2.eval(lua)).value();
 		return new LuaNumber( n1 / n2 );
--- a/src/luan/interp/EnvExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/EnvExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,14 +1,12 @@
 package luan.interp;
 
-import luan.LuaState;
-
 
 final class EnvExpr implements Expr {
 	static final EnvExpr INSTANCE = new EnvExpr();
 
 	private EnvExpr() {}
 
-	@Override public Object eval(LuaState lua) {
+	@Override public Object eval(LuaStateImpl lua) {
 		return lua.env();
 	}
 }
--- a/src/luan/interp/EqExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/EqExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -3,7 +3,6 @@
 import luan.Lua;
 import luan.LuaNumber;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class EqExpr extends BinaryOpExpr {
@@ -12,7 +11,7 @@
 		super(op1,op2);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		Object v1 = op1.eval(lua);
 		Object v2 = op2.eval(lua);
 		return v1 == v2 || v1 != null && v1.equals(v2);
--- a/src/luan/interp/ExpList.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/ExpList.java	Thu Dec 13 02:50:04 2012 +0000
@@ -4,13 +4,12 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class ExpList implements Expressions {
 
 	private interface Adder {
-		public void addTo(LuaState lua,List<Object> list) throws LuaException;
+		public void addTo(LuaStateImpl lua,List<Object> list) throws LuaException;
 	}
 
 	private static class ExprAdder implements Adder {
@@ -20,7 +19,7 @@
 			this.expr = expr;
 		}
 
-		public void addTo(LuaState lua,List<Object> list) throws LuaException {
+		public void addTo(LuaStateImpl lua,List<Object> list) throws LuaException {
 			list.add( expr.eval(lua) );
 		}
 
@@ -33,7 +32,7 @@
 			this.expressions = expressions;
 		}
 
-		public void addTo(LuaState lua,List<Object> list) throws LuaException {
+		public void addTo(LuaStateImpl lua,List<Object> list) throws LuaException {
 			for( Object val : expressions.eval(lua) ) {
 				list.add( val );
 			}
@@ -71,7 +70,7 @@
 	private static final Object[] EMPTY = new Object[0];
 
 	static final Expressions emptyExpList = new Expressions() {
-		@Override public Object[] eval(LuaState lua) {
+		@Override public Object[] eval(LuaStateImpl lua) {
 			return EMPTY;
 		}
 	};
@@ -83,7 +82,7 @@
 			this.expr = expr;
 		}
 
-		@Override public Object[] eval(LuaState lua) throws LuaException {
+		@Override public Object[] eval(LuaStateImpl lua) throws LuaException {
 			return new Object[]{expr.eval(lua)};
 		}
 	}
@@ -94,7 +93,7 @@
 		this.adders = adders;
 	}
 
-	@Override public Object[] eval(LuaState lua) throws LuaException {
+	@Override public Object[] eval(LuaStateImpl lua) throws LuaException {
 		List<Object> list = new ArrayList<Object>();
 		for( Adder adder : adders ) {
 			adder.addTo(lua,list);
--- a/src/luan/interp/Expr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/Expr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,9 +1,8 @@
 package luan.interp;
 
-import luan.LuaState;
 import luan.LuaException;
 
 
 interface Expr {
-	public Object eval(LuaState lua) throws LuaException;
+	public Object eval(LuaStateImpl lua) throws LuaException;
 }
--- a/src/luan/interp/Expressions.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/Expressions.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,9 +1,8 @@
 package luan.interp;
 
 import luan.LuaException;
-import luan.LuaState;
 
 
-public interface Expressions {
-	public Object[] eval(LuaState lua) throws LuaException;
+interface Expressions {
+	public Object[] eval(LuaStateImpl lua) throws LuaException;
 }
--- a/src/luan/interp/ExpressionsExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/ExpressionsExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -3,7 +3,6 @@
 import java.util.List;
 import luan.Lua;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class ExpressionsExpr implements Expr {
@@ -13,7 +12,7 @@
 		this.expressions = expressions;
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		Object[] a = expressions.eval(lua);
 		return a.length==0 ? null : a[0];
 	}
--- a/src/luan/interp/ExpressionsStmt.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/ExpressionsStmt.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,6 +1,5 @@
 package luan.interp;
 
-import luan.LuaState;
 import luan.LuaException;
 
 
@@ -11,7 +10,7 @@
 		this.expressions = expressions;
 	}
 
-	@Override public void eval(LuaState lua) throws LuaException {
+	@Override public void eval(LuaStateImpl lua) throws LuaException {
 		expressions.eval(lua);
 	}
 
--- a/src/luan/interp/FnCall.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/FnCall.java	Thu Dec 13 02:50:04 2012 +0000
@@ -3,7 +3,6 @@
 import luan.Lua;
 import luan.LuaFunction;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class FnCall implements Expressions {
@@ -15,7 +14,7 @@
 		this.args = args;
 	}
 
-	@Override public Object[] eval(LuaState lua) throws LuaException {
+	@Override public Object[] eval(LuaStateImpl lua) throws LuaException {
 		LuaFunction fn = Lua.checkFunction( fnExpr.eval(lua) );
 		return fn.call( lua, args.eval(lua) );
 	}
--- a/src/luan/interp/GenericForStmt.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/GenericForStmt.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,7 +1,6 @@
 package luan.interp;
 
 import luan.Lua;
-import luan.LuaState;
 import luan.LuaException;
 import luan.LuaFunction;
 
@@ -19,7 +18,7 @@
 		this.block = block;
 	}
 
-	@Override public void eval(LuaState lua) throws LuaException {
+	@Override public void eval(LuaStateImpl lua) throws LuaException {
 		LuaFunction iter = Lua.checkFunction( iterExpr.eval(lua) );
 		Object[] stack = lua.stack();
 		try {
--- a/src/luan/interp/GetExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/GetExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -2,7 +2,6 @@
 
 import luan.Lua;
 import luan.LuaException;
-import luan.LuaState;
 import luan.LuaTable;
 
 
@@ -12,7 +11,7 @@
 		super(op1,op2);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		Object t = op1.eval(lua);
 		if( t instanceof LuaTable ) {
 			LuaTable tbl = (LuaTable)t;
--- a/src/luan/interp/GetLocalVar.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/GetLocalVar.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,7 +1,5 @@
 package luan.interp;
 
-import luan.LuaState;
-
 
 final class GetLocalVar implements Expr {
 	private final int index;
@@ -10,7 +8,7 @@
 		this.index = index;
 	}
 
-	@Override public Object eval(LuaState lua) {
+	@Override public Object eval(LuaStateImpl lua) {
 		return lua.stack()[index];
 	}
 }
--- a/src/luan/interp/IfStmt.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/IfStmt.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,7 +1,6 @@
 package luan.interp;
 
 import luan.Lua;
-import luan.LuaState;
 import luan.LuaException;
 
 
@@ -16,7 +15,7 @@
 		this.elseStmt = elseStmt;
 	}
 
-	@Override public void eval(LuaState lua) throws LuaException {
+	@Override public void eval(LuaStateImpl lua) throws LuaException {
 		if( Lua.toBoolean( cnd.eval(lua) ) ) {
 			thenStmt.eval(lua);
 		} else {
--- a/src/luan/interp/LeExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/LeExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -3,7 +3,6 @@
 import luan.Lua;
 import luan.LuaNumber;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class LeExpr extends BinaryOpExpr {
@@ -12,7 +11,7 @@
 		super(op1,op2);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		Object v1 = op1.eval(lua);
 		Object v2 = op2.eval(lua);
 		if( v1 instanceof LuaNumber && v2 instanceof LuaNumber ) {
--- a/src/luan/interp/LenExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/LenExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -4,7 +4,6 @@
 import luan.LuaNumber;
 import luan.LuaTable;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class LenExpr extends UnaryOpExpr {
@@ -13,7 +12,7 @@
 		super(op);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		return new LuaNumber( length(op.eval(lua)) );
 	}
 
--- a/src/luan/interp/LtExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/LtExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -3,7 +3,6 @@
 import luan.Lua;
 import luan.LuaNumber;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class LtExpr extends BinaryOpExpr {
@@ -12,7 +11,7 @@
 		super(op1,op2);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		Object v1 = op1.eval(lua);
 		Object v2 = op2.eval(lua);
 		if( v1 instanceof LuaNumber && v2 instanceof LuaNumber ) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/interp/LuaClosure.java	Thu Dec 13 02:50:04 2012 +0000
@@ -0,0 +1,52 @@
+package luan.interp;
+
+import luan.LuaFunction;
+import luan.LuaState;
+import luan.LuaException;
+
+
+final class LuaClosure extends LuaFunction {
+	private final Chunk chunk;
+
+	LuaClosure(Chunk chunk,LuaStateImpl lua) {
+		this.chunk = chunk;
+	}
+
+	public Object[] call(LuaState luaState,Object... args) throws LuaException {
+		LuaStateImpl lua = (LuaStateImpl)luaState;
+		Chunk chunk = this.chunk;
+		while(true) {
+			Object[] varArgs = null;
+			if( chunk.isVarArg ) {
+				if( args.length > chunk.numArgs ) {
+					varArgs = new Object[ args.length - chunk.numArgs ];
+					for( int i=0; i<varArgs.length; i++ ) {
+						varArgs[i] = args[chunk.numArgs+i];
+					}
+				} else {
+					varArgs = LuaFunction.EMPTY_RTN;
+				}
+			}
+			Object[] stack = lua.newStack(chunk.stackSize,varArgs);
+			final int n = Math.min(args.length,chunk.numArgs);
+			for( int i=0; i<n; i++ ) {
+				stack[i] = args[i];
+			}
+			Object[] returnValues;
+			LuaClosure tailFn;
+			try {
+				chunk.block.eval(lua);
+			} catch(ReturnException e) {
+			} finally {
+				returnValues = lua.returnValues;
+				tailFn = lua.tailFn;
+				lua.popStack();
+			}
+			if( tailFn == null )
+				return returnValues;
+			chunk = tailFn.chunk;
+			args = returnValues;
+		}
+	}
+
+}
--- a/src/luan/interp/LuaCompiler.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/LuaCompiler.java	Thu Dec 13 02:50:04 2012 +0000
@@ -24,11 +24,15 @@
 			final Expressions expressions = (Expressions)resultValue;
 			return new LuaFunction() {
 				public Object[] call(LuaState lua,Object... args) throws LuaException {
-					return expressions.eval(lua);
+					return expressions.eval((LuaStateImpl)lua);
 				}
 			};
 		}
 		Chunk chunk = (Chunk)resultValue;
-		return chunk.newClosure(lua);
+		return chunk.newClosure((LuaStateImpl)lua);
+	}
+
+	public static LuaState newLuaState() {
+		return new LuaStateImpl();
 	}
 }
--- a/src/luan/interp/LuaParser.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/LuaParser.java	Thu Dec 13 02:50:04 2012 +0000
@@ -978,20 +978,4 @@
 		return true;
 	}
 
-	// for testing
-	public static void main(String[] args) throws Exception {
-		LuaParser parser = Parboiled.createParser(LuaParser.class);
-		while( true ) {
-			String input = new Scanner(System.in).nextLine();
-			ParsingResult<?> result = new ReportingParseRunner(parser.Target()).run(input);
-			if( result.hasErrors() ) {
-				System.out.println("Parse Errors:\n" + ErrorUtils.printParseErrors(result));
-			} else {
-				Expr expr = expr(result.resultValue);
-				LuaState lua = new LuaState();
-				Object val = expr.eval(lua);
-				System.out.println("Result: "+Lua.toString(val));
-			}
-		}
-	}
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/interp/LuaStateImpl.java	Thu Dec 13 02:50:04 2012 +0000
@@ -0,0 +1,50 @@
+package luan.interp;
+
+import luan.LuaState;
+import luan.LuaTable;
+import luan.LuaFunction;
+
+
+final class LuaStateImpl implements LuaState {
+	private final LuaTable env = new LuaTable();
+
+	public LuaTable env() {
+		return env;
+	}
+
+
+	private static class LuaStack {
+		final LuaStack previousStack;
+		final Object[] a;
+		final Object[] varArgs;
+
+		LuaStack( LuaStack previousStack, int stackSize, Object[] varArgs) {
+			this.previousStack = previousStack;
+			this.a = new Object[stackSize];
+			this.varArgs = varArgs;
+		}
+	}
+
+	private LuaStack stack = null;
+	public Object[] returnValues;
+	public LuaClosure tailFn;
+
+	Object[] newStack(int stackSize, Object[] varArgs) {
+		stack = new LuaStack(stack,stackSize,varArgs);
+		return stack.a;
+	}
+
+	void popStack() {
+		returnValues = LuaFunction.EMPTY_RTN;
+		tailFn = null;
+		stack = stack.previousStack;
+	}
+
+	public Object[] stack() {
+		return stack.a;
+	}
+
+	public Object[] varArgs() {
+		return stack.varArgs;
+	}
+}
--- a/src/luan/interp/ModExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/ModExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -3,7 +3,6 @@
 import luan.Lua;
 import luan.LuaNumber;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class ModExpr extends BinaryOpExpr {
@@ -12,7 +11,7 @@
 		super(op1,op2);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		double n1 = Lua.checkNumber(op1.eval(lua)).value();
 		double n2 = Lua.checkNumber(op2.eval(lua)).value();
 		return new LuaNumber( n1 % n2 );
--- a/src/luan/interp/MulExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/MulExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -3,7 +3,6 @@
 import luan.Lua;
 import luan.LuaNumber;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class MulExpr extends BinaryOpExpr {
@@ -12,7 +11,7 @@
 		super(op1,op2);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		double n1 = Lua.checkNumber(op1.eval(lua)).value();
 		double n2 = Lua.checkNumber(op2.eval(lua)).value();
 		return new LuaNumber( n1 * n2 );
--- a/src/luan/interp/NotExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/NotExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -2,7 +2,6 @@
 
 import luan.Lua;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class NotExpr extends UnaryOpExpr {
@@ -11,7 +10,7 @@
 		super(op);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		return !Lua.toBoolean(op.eval(lua));
 	}
 }
--- a/src/luan/interp/NumericForStmt.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/NumericForStmt.java	Thu Dec 13 02:50:04 2012 +0000
@@ -2,7 +2,6 @@
 
 import luan.Lua;
 import luan.LuaNumber;
-import luan.LuaState;
 import luan.LuaException;
 
 
@@ -21,7 +20,7 @@
 		this.block = block;
 	}
 
-	@Override public void eval(LuaState lua) throws LuaException {
+	@Override public void eval(LuaStateImpl lua) throws LuaException {
 		double v = Lua.checkNumber( fromExpr.eval(lua) ).value();
 		double limit = Lua.checkNumber( toExpr.eval(lua) ).value();
 		double step = Lua.checkNumber( stepExpr.eval(lua) ).value();
--- a/src/luan/interp/OrExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/OrExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -2,7 +2,6 @@
 
 import luan.Lua;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class OrExpr extends BinaryOpExpr {
@@ -11,7 +10,7 @@
 		super(op1,op2);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		Object v1 = op1.eval(lua);
 		return Lua.toBoolean(v1) ? v1 : op2.eval(lua);
 	}
--- a/src/luan/interp/PowExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/PowExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -3,7 +3,6 @@
 import luan.Lua;
 import luan.LuaNumber;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class PowExpr extends BinaryOpExpr {
@@ -12,7 +11,7 @@
 		super(op1,op2);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		double n1 = Lua.checkNumber(op1.eval(lua)).value();
 		double n2 = Lua.checkNumber(op2.eval(lua)).value();
 		return new LuaNumber( Math.pow(n1,n2) );
--- a/src/luan/interp/RepeatStmt.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/RepeatStmt.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,7 +1,6 @@
 package luan.interp;
 
 import luan.Lua;
-import luan.LuaState;
 import luan.LuaException;
 
 
@@ -14,7 +13,7 @@
 		this.cnd = cnd;
 	}
 
-	@Override public void eval(LuaState lua) throws LuaException {
+	@Override public void eval(LuaStateImpl lua) throws LuaException {
 		try {
 			do {
 				doStmt.eval(lua);
--- a/src/luan/interp/ReturnException.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/ReturnException.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,4 +1,4 @@
 package luan.interp;
 
 
-public final class ReturnException extends RuntimeException {}
+final class ReturnException extends RuntimeException {}
--- a/src/luan/interp/ReturnStmt.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/ReturnStmt.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,10 +1,8 @@
 package luan.interp;
 
 import luan.Lua;
-import luan.LuaState;
 import luan.LuaException;
 import luan.LuaFunction;
-import luan.LuaClosure;
 
 
 final class ReturnStmt implements Stmt {
@@ -23,7 +21,7 @@
 		}
 	}
 
-	@Override public void eval(LuaState lua) throws LuaException {
+	@Override public void eval(LuaStateImpl lua) throws LuaException {
 		lua.returnValues = expressions.eval(lua);
 		if( tailFnExpr != null ) {
 			LuaFunction tailFn = Lua.checkFunction( tailFnExpr.eval(lua) );
--- a/src/luan/interp/SetLocalVar.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/SetLocalVar.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,7 +1,5 @@
 package luan.interp;
 
-import luan.LuaState;
-
 
 final class SetLocalVar implements Settable {
 	private final int index;
@@ -10,7 +8,7 @@
 		this.index = index;
 	}
 
-	@Override public void set(LuaState lua,Object value) {
+	@Override public void set(LuaStateImpl lua,Object value) {
 		lua.stack()[index] = value;
 	}
 }
--- a/src/luan/interp/SetStmt.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/SetStmt.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,7 +1,6 @@
 package luan.interp;
 
 import luan.Lua;
-import luan.LuaState;
 import luan.LuaException;
 
 
@@ -18,7 +17,7 @@
 		this.expressions = expressions;
 	}
 
-	@Override public void eval(LuaState lua) throws LuaException {
+	@Override public void eval(LuaStateImpl lua) throws LuaException {
 		final Object[] vals = expressions.eval(lua);
 		for( int i=0; i<vars.length; i++ ) {
 			Object val = i < vals.length ? vals[i] : null;
--- a/src/luan/interp/SetTableEntry.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/SetTableEntry.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,6 +1,5 @@
 package luan.interp;
 
-import luan.LuaState;
 import luan.LuaException;
 import luan.LuaTable;
 import luan.Lua;
@@ -15,7 +14,7 @@
 		this.keyExpr = keyExpr;
 	}
 
-	@Override public void set(LuaState lua,Object value) throws LuaException {
+	@Override public void set(LuaStateImpl lua,Object value) throws LuaException {
 		Object t = tableExpr.eval(lua);
 		if( !(t instanceof LuaTable) )
 			throw new LuaException( "attempt to index a " + Lua.type(t) + " value" );
--- a/src/luan/interp/Settable.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/Settable.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,9 +1,8 @@
 package luan.interp;
 
-import luan.LuaState;
 import luan.LuaException;
 
 
 interface Settable {
-	public void set(LuaState lua,Object value) throws LuaException;
+	public void set(LuaStateImpl lua,Object value) throws LuaException;
 }
--- a/src/luan/interp/Stmt.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/Stmt.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,13 +1,12 @@
 package luan.interp;
 
-import luan.LuaState;
 import luan.LuaException;
 
 
-public interface Stmt {
-	public void eval(LuaState lua) throws LuaException;
+interface Stmt {
+	public void eval(LuaStateImpl lua) throws LuaException;
 
 	static final Stmt EMPTY = new Stmt() {
-		public void eval(LuaState lua) {}
+		public void eval(LuaStateImpl lua) {}
 	};
 }
--- a/src/luan/interp/SubExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/SubExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -3,7 +3,6 @@
 import luan.Lua;
 import luan.LuaNumber;
 import luan.LuaException;
-import luan.LuaState;
 
 
 final class SubExpr extends BinaryOpExpr {
@@ -12,7 +11,7 @@
 		super(op1,op2);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		double n1 = Lua.checkNumber(op1.eval(lua)).value();
 		double n2 = Lua.checkNumber(op2.eval(lua)).value();
 		return new LuaNumber( n1 - n2 );
--- a/src/luan/interp/TableExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/TableExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,7 +1,6 @@
 package luan.interp;
 
 import luan.LuaException;
-import luan.LuaState;
 import luan.LuaTable;
 import luan.LuaNumber;
 
@@ -26,7 +25,7 @@
 		this.expressions = expressions;
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		LuaTable table = new LuaTable();
 		for( Field field : fields ) {
 			table.set( field.key.eval(lua), field.value.eval(lua) );
--- a/src/luan/interp/UnmExpr.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/UnmExpr.java	Thu Dec 13 02:50:04 2012 +0000
@@ -3,7 +3,6 @@
 import luan.Lua;
 import luan.LuaNumber;
 import luan.LuaException;
-import luan.LuaState;
 
 
 // unary minus
@@ -13,7 +12,7 @@
 		super(op);
 	}
 
-	@Override public Object eval(LuaState lua) throws LuaException {
+	@Override public Object eval(LuaStateImpl lua) throws LuaException {
 		double n = Lua.checkNumber(op.eval(lua)).value();
 		return new LuaNumber( -n );
 	}
--- a/src/luan/interp/VarArgs.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/VarArgs.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,14 +1,12 @@
 package luan.interp;
 
-import luan.LuaState;
-
 
 final class VarArgs implements Expressions {
 	static final VarArgs INSTANCE = new VarArgs();
 
 	private VarArgs() {}
 
-	@Override public Object[] eval(LuaState lua) {
+	@Override public Object[] eval(LuaStateImpl lua) {
 		return lua.varArgs();
 	}
 }
--- a/src/luan/interp/WhileStmt.java	Fri Dec 07 20:22:19 2012 +0000
+++ b/src/luan/interp/WhileStmt.java	Thu Dec 13 02:50:04 2012 +0000
@@ -1,7 +1,6 @@
 package luan.interp;
 
 import luan.Lua;
-import luan.LuaState;
 import luan.LuaException;
 
 
@@ -14,7 +13,7 @@
 		this.doStmt = doStmt;
 	}
 
-	@Override public void eval(LuaState lua) throws LuaException {
+	@Override public void eval(LuaStateImpl lua) throws LuaException {
 		try {
 			while( Lua.toBoolean( cnd.eval(lua) ) ) {
 				doStmt.eval(lua);