changeset 670:58ebfec6178b

all luan now compiles
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 12 Apr 2016 01:05:57 -0600
parents e320488819b6
children 82f130eba7b0
files core/src/luan/impl/Block.java core/src/luan/impl/Closure.java core/src/luan/impl/ForStmt.java core/src/luan/impl/GetLocalVar.java core/src/luan/impl/GetUpVar.java core/src/luan/impl/LuanCompiler.java core/src/luan/impl/LuanImpl.java core/src/luan/impl/LuanParser.java core/src/luan/impl/LuanStateImpl.java core/src/luan/impl/Pointer.java core/src/luan/impl/SetLocalVar.java core/src/luan/impl/SetUpVar.java core/src/luan/impl/ThemeParser.java core/src/luan/impl/UpValue.java core/src/luan/impl/VarArgs.java
diffstat 15 files changed, 325 insertions(+), 563 deletions(-) [+]
line wrap: on
line diff
--- a/core/src/luan/impl/Block.java	Mon Apr 11 16:00:44 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-package luan.impl;
-
-import luan.LuanException;
-
-
-final class Block implements Stmt {
-	final Stmt[] stmts;
-	private final int stackStart;
-	private final int stackEnd;
-
-	Block(Stmt[] stmts,int stackStart,int stackEnd) {
-		if( stmts.length==0 )
-			throw new RuntimeException("empty block");
-		this.stmts = stmts;
-		this.stackStart = stackStart;
-		this.stackEnd = stackEnd;
-	}
-
-	@Override public void eval(LuanStateImpl luan) throws LuanException {
-		try {
-			for( Stmt stmt : stmts ) {
-				stmt.eval(luan);
-			}
-		} finally {
-			luan.stackClear(stackStart,stackEnd);
-		}
-	}
-
-}
--- a/core/src/luan/impl/Closure.java	Mon Apr 11 16:00:44 2016 -0600
+++ b/core/src/luan/impl/Closure.java	Tue Apr 12 01:05:57 2016 -0600
@@ -9,19 +9,10 @@
 
 
 public abstract class Closure extends LuanFunction implements DeepCloneable, Cloneable {
-	private final int stackSize;
-	private final int numArgs;
-	private final boolean isVarArg;
-	private UpValue[] upValues;
+	public Pointer[] upValues;
 
-	public Closure(LuanStateImpl luan,int stackSize,int numArgs,boolean isVarArg,UpValue.Getter[] upValueGetters) throws LuanException {
-		this.stackSize = stackSize;
-		this.numArgs = numArgs;
-		this.isVarArg = isVarArg;
-		this.upValues = new UpValue[upValueGetters.length];
-		for( int i=0; i<upValues.length; i++ ) {
-			upValues[i] = upValueGetters[i].get(luan);
-		}
+	public Closure(int nUpValues) throws LuanException {
+		this.upValues = new Pointer[nUpValues];
 	}
 
 	@Override public Closure shallowClone() {
@@ -33,39 +24,19 @@
 	}
 
 	@Override public void deepenClone(DeepCloneable clone,DeepCloner cloner) {
-		((Closure)clone).upValues = (UpValue[])cloner.deepClone(upValues);
-	}
-
-	UpValue[] upValues() {
-		return upValues;
+		((Closure)clone).upValues = (Pointer[])cloner.deepClone(upValues);
 	}
 
-	@Override public Object call(LuanState ls,Object[] args) throws LuanException {
+	@Override public final Object call(LuanState ls,Object[] args) throws LuanException {
 		LuanStateImpl luan = (LuanStateImpl)ls;
-		Object[] varArgs = null;
-		if( isVarArg ) {
-			if( args.length > numArgs ) {
-				varArgs = new Object[ args.length - numArgs ];
-				for( int i=0; i<varArgs.length; i++ ) {
-					varArgs[i] = args[numArgs+i];
-				}
-			} else {
-				varArgs = LuanFunction.NOTHING;
-			}
-		}
-		Object[] stack = luan.newFrame(this,stackSize,varArgs);
-		final int n = Math.min(args.length,numArgs);
-		for( int i=0; i<n; i++ ) {
-			stack[i] = args[i];
-		}
+		Closure old = luan.closure;
+		luan.closure = this;
 		try {
-			return run(luan);
-		} catch(StackOverflowError e) {
-			throw new LuanException( "stack overflow", e );
+			return doCall(luan,args);
 		} finally {
-			luan.popFrame();
-		}
+			luan.closure = old;
+		}	
 	}
 
-	public abstract Object run(LuanStateImpl luan) throws LuanException;
+	public abstract Object doCall(LuanState luan,Object[] args) throws LuanException;
 }
--- a/core/src/luan/impl/ForStmt.java	Mon Apr 11 16:00:44 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-package luan.impl;
-
-import luan.Luan;
-import luan.LuanException;
-import luan.LuanFunction;
-
-
-final class ForStmt extends CodeImpl implements Stmt {
-	private final int iVars;
-	private final int nVars;
-	private final Expr iterExpr;
-	private final Stmt block;
-
-	ForStmt(int iVars,int nVars,Expr iterExpr,Stmt block) {
-		this.iVars = iVars;
-		this.nVars = nVars;
-		this.iterExpr = iterExpr;
-		this.block = block;
-	}
-
-	@Override public void eval(LuanStateImpl luan) throws LuanException {
-		Object fnObj = iterExpr.eval(luan);
-		try {
-			LuanFunction iter = Luan.checkFunction(fnObj);
-			while(true) {
-				Object vals = iter.call(luan);
-				if( vals==null )
-					break;
-				if( vals instanceof Object[] ) {
-					Object[] a = (Object[])vals;
-					if( a.length==0 || a[0]==null )
-						break;
-					for( int i=0; i<nVars; i++ ) {
-						luan.stackSet( iVars+i, i < a.length ? a[i] : null );
-					}
-				} else {
-					luan.stackSet( iVars, vals );
-					for( int i=1; i<nVars; i++ ) {
-						luan.stackSet( iVars+i, null );
-					}
-				}
-				block.eval(luan);
-			}
-		} catch(BreakException e) {
-		} finally {
-			luan.stackClear(iVars,iVars+nVars);
-		}
-	}
-
-}
--- a/core/src/luan/impl/GetLocalVar.java	Mon Apr 11 16:00:44 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-package luan.impl;
-
-
-final class GetLocalVar extends CodeImpl implements Expr {
-	private final int index;
-
-	GetLocalVar(int index) {
-		if( index < 0 )  throw new RuntimeException();
-		this.index = index;
-	}
-
-	@Override public Object eval(LuanStateImpl luan) {
-		return luan.stackGet(index);
-	}
-}
--- a/core/src/luan/impl/GetUpVar.java	Mon Apr 11 16:00:44 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-package luan.impl;
-
-
-final class GetUpVar extends CodeImpl implements Expr {
-	private final int index;
-
-	GetUpVar(int index) {
-		if( index < 0 )  throw new RuntimeException();
-		this.index = index;
-	}
-
-	@Override public Object eval(LuanStateImpl luan) {
-		return luan.closure().upValues()[index].get();
-	}
-}
--- a/core/src/luan/impl/LuanCompiler.java	Mon Apr 11 16:00:44 2016 -0600
+++ b/core/src/luan/impl/LuanCompiler.java	Tue Apr 12 01:05:57 2016 -0600
@@ -14,13 +14,15 @@
 	private LuanCompiler() {}  // never
 
 	public static LuanFunction compile(LuanState luan,String sourceName,String sourceText,LuanTable env,boolean allowExpr) throws LuanException {
-		LuanParser parser = new LuanParser(sourceName,sourceText,env);
-		parser.addVar( "java", JavaLuan.javaFn );
-		parser.addVar( "require", PackageLuan.requireFn );
+		LuanParser parser = new LuanParser(sourceName,sourceText);
+		parser.addVar( env!=null ? "_ENV" : null );
+		parser.addVar( "java" );
+		parser.addVar( "require" );
 		Class fnClass = parse(parser,allowExpr);
 		final LuanStateImpl luanImpl = (LuanStateImpl)luan;
+		Closure closure;
 		try {
-			return (LuanFunction)fnClass.getConstructor(LuanStateImpl.class).newInstance(luanImpl);
+			closure = (Closure)fnClass.getConstructor(LuanState.class).newInstance(luanImpl);
 		} catch(NoSuchMethodException e) {
 			throw new RuntimeException(e);
 		} catch(InstantiationException e) {
@@ -30,6 +32,10 @@
 		} catch(InvocationTargetException e) {
 			throw new RuntimeException(e);
 		}
+		closure.upValues[0].o = env!=null ? env : new LuanTable();
+		closure.upValues[1].o = JavaLuan.javaFn;
+		closure.upValues[2].o = PackageLuan.requireFn;
+		return closure;
 	}
 
 	private static Class parse(LuanParser parser,boolean allowExpr) throws LuanException {
--- a/core/src/luan/impl/LuanImpl.java	Mon Apr 11 16:00:44 2016 -0600
+++ b/core/src/luan/impl/LuanImpl.java	Tue Apr 12 01:05:57 2016 -0600
@@ -14,7 +14,7 @@
 public final class LuanImpl {
 	private LuanImpl() {}  // never
 
-
+/*
 	private static List list = new ArrayList();
 
 	static int addObj(Object obj) {
@@ -26,7 +26,7 @@
 	public static Object getObj(int i) {
 		return list.get(i);
 	}
-
+*/
 
 	public static int len(LuanState luan,Object o) throws LuanException {
 		if( o instanceof String ) {
@@ -170,7 +170,7 @@
 
 	public static void nop(Object o) {}
 
-
+/*
 	public static void set(LuanStateImpl luan,Settable[] vars,Object obj) throws LuanException {
 		if( obj instanceof Object[] ) {
 			Object[] vals = (Object[])obj;
@@ -185,7 +185,7 @@
 			}
 		}
 	}
-
+*/
 	public static void put(LuanState luan,Object t,Object key,Object value) throws LuanException {
 		if( t instanceof LuanTable ) {
 			LuanTable tbl = (LuanTable)t;
@@ -207,6 +207,17 @@
 		return i<a.length ? a[i] : null;
 	}
 
+	public static Object[] varArgs(Object o,int i) {
+		if( !(o instanceof Object[]) )
+			return i==0 ? new Object[]{o} : LuanFunction.NOTHING;
+		Object[] a = (Object[])o;
+		if( i >= a.length )
+			return LuanFunction.NOTHING;
+		Object[] rtn = new Object[a.length - i];
+		System.arraycopy(a,i,rtn,0,rtn.length);
+		return rtn;
+	}
+
 	public static Object[] concatArgs(Object o1,Object o2) {
 		if( o1 instanceof Object[] ) {
 			Object[] a1 = (Object[])o1;
--- a/core/src/luan/impl/LuanParser.java	Mon Apr 11 16:00:44 2016 -0600
+++ b/core/src/luan/impl/LuanParser.java	Tue Apr 12 01:05:57 2016 -0600
@@ -5,7 +5,6 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.ArrayList;
-import java.util.Scanner;
 import luan.Luan;
 import luan.LuanState;
 import luan.LuanTable;
@@ -14,61 +13,134 @@
 
 final class LuanParser {
 
-	private static final class Frame {
+	private interface Sym {
+		public ExpString exp();
+	}
+
+	private int symCounter = 0;
+
+	private class LocalSym implements Sym {
+		final String name;
+		final String javaName;
+		String pointer = null;
+
+		LocalSym(String name) {
+			this.name = name;
+			this.javaName = name + "_" + (++symCounter);
+		}
+
+		String declaration() {
+			if( pointer==null )
+				return "Object " + javaName + " = null;\n";
+			else
+				return "final Pointer " + javaName + " = " + pointer + ";\n";
+		}
+
+		String ref() {
+			if( pointer==null )
+				return javaName;
+			else
+				return javaName + ".o";
+		}
+
+		@Override public ExpString exp() {
+			ExpString exp = new ExpString(true,false);
+			exp.list.add( new Object() {
+				@Override public String toString() {
+					return ref();
+				}
+			} );
+			return exp;
+		}
+	}
+
+	private class UpSym implements Sym {
+		final String name;
+		final int i;
+		final String value;
+
+		UpSym(String name,int i,String value) {
+			this.name = name;
+			this.i = i;
+			this.value = value;
+		}
+
+		String init() {
+			return "upValues[" + i + "] = " + value + ";\n";
+		}
+
+		String ref() {
+			return "upValues[" + i + "].o";
+		}
+
+		@Override public ExpString exp() {
+			ExpString exp = new ExpString(true,false);
+			exp.list.add( new Object() {
+				@Override public String toString() {
+					return ref();
+				}
+			} );
+			return exp;
+		}
+	}
+
+	private final class Frame {
 		final Frame parent;
-		final List<String> symbols = new ArrayList<String>();
-		int stackSize = 0;
+		final List<LocalSym> symbols = new ArrayList<LocalSym>();
 		int loops = 0;
 		boolean isVarArg = false;
-		final List<String> upValueSymbols = new ArrayList<String>();
-		final List<UpValue.Getter> upValueGetters = new ArrayList<UpValue.Getter>();
+		final List<UpSym> upValueSymbols = new ArrayList<UpSym>();
 
-		Frame(LuanTable java) {
+		Frame() {
 			this.parent = null;
-			upValueSymbols.add(JAVA);
-			upValueGetters.add(new UpValue.ValueGetter(java));
 		}
 
 		Frame(Frame parent) {
 			this.parent = parent;
-			if( upValueIndex(JAVA) != 0 )
-				throw new RuntimeException();
 		}
 
-		int stackIndex(String name) {
-			int i = symbols.size();
-			while( --i >= 0 ) {
-				if( symbols.get(i).equals(name) )
-					return i;
-			}
-			return -1;
+		LocalSym addLocalSym(String name) {
+			LocalSym sym = new LocalSym(name);
+			symbols.add(sym);
+			return sym;
+		}
+
+		UpSym addUpSym(String name,String value) {
+			UpSym sym = new UpSym( name, upValueSymbols.size(), value );
+			upValueSymbols.add(sym);
+			return sym;
 		}
 
-		int upValueIndex(String name) {
-			int i = upValueSymbols.size();
+		LocalSym getLocalSym(String name) {
+			int i = symbols.size();
 			while( --i >= 0 ) {
-				if( upValueSymbols.get(i).equals(name) )
-					return i;
+				LocalSym sym = symbols.get(i);
+				if( sym.name.equals(name) )
+					return sym;
 			}
-			if( parent==null )
-				return -1;
-			i = parent.stackIndex(name);
-			if( i != -1 ) {
-				upValueGetters.add(new UpValue.StackGetter(i));
-			} else {
-				i = parent.upValueIndex(name);
-				if( i == -1 )
-					return -1;
-				upValueGetters.add(new UpValue.NestedGetter(i));
-			}
-			upValueSymbols.add(name);
-			return upValueSymbols.size() - 1;
+			return null;
 		}
 
-		void addUpValueGetter(String name,UpValue.Getter upValueGetter) {
-			upValueSymbols.add(name);
-			upValueGetters.add(upValueGetter);
+		UpSym getUpSym(String name) {
+			for( UpSym upSym : upValueSymbols ) {
+				if( upSym.name.equals(name) )
+					return upSym;
+			}
+			for( Frame f=parent; f!=null; f=f.parent ) {
+				LocalSym sym = f.getLocalSym(name);
+				if( sym != null ) {
+					sym.pointer = "new Pointer()";
+					return addUpSym(name,sym.javaName);
+				}
+			}
+			return null;
 		}
+
+		Sym getSym(String name) {
+			Sym sym = getLocalSym(name);
+			return sym != null ? sym : getUpSym(name);
+		}
+
 	}
 
 	private static class In {
@@ -91,61 +163,56 @@
 		}
 	}
 
-	private static final String JAVA = "-JAVA-";  // inaccessible from Luan
-	private static final String _ENV = "_ENV";
-	private static final UpValue.Getter[] NO_UP_VALUE_GETTERS = new UpValue.Getter[0];
-
 //	final LuanSource source;
 	private Frame frame;
 	private final Parser parser;
+	private final StmtString top = new StmtString();
 
-	LuanParser(String sourceName,String sourceText,LuanTable env) {
+	LuanParser(String sourceName,String sourceText) {
 //		this.source = source;
-		this.frame = new Frame( env!=null ? env : new LuanTable() );
+		this.frame = new Frame();
 		this.parser = new Parser(sourceName,sourceText);
-		if( env != null )
-			addVar(_ENV,env);
 	}
 
-	void addVar(String name,Object value) {
-		frame.addUpValueGetter(name,new UpValue.ValueGetter(value));
-	}
-
-	private List<String> symbols() {
-		return frame.symbols;
+	void addVar(String name) {
+		UpSym upSym = frame.addUpSym( "-ADDED-" ,"new Pointer()");
+		if( name != null ) {
+			LocalSym sym = frame.addLocalSym( name );
+			sym.pointer = "upValues[" + upSym.i + "]";
+			top.list.add( sym.declaration() );
+		}
 	}
 
 	private int symbolsSize() {
 		return frame.symbols.size();
 	}
 
-	private void addSymbol(String name) {
-		frame.symbols.add(name);
-		if( frame.stackSize < symbolsSize() )
-			frame.stackSize = symbolsSize();
+	private void addSymbol(String name,StmtString stmt) {
+		final LocalSym sym = frame.addLocalSym(name);
+		stmt.list.add( new Object() {
+			@Override public String toString() {
+				return sym.declaration();
+			}
+		} );
 	}
 
-	private void addSymbols(List<String> names) {
-		frame.symbols.addAll(names);
-		if( frame.stackSize < symbolsSize() )
-			frame.stackSize = symbolsSize();
+	private void addSymbols(List<String> names,StmtString stmt) {
+		for( String name : names ) {
+			addSymbol(name,stmt);
+		}
 	}
 
-	private int stackIndex(String name) {
-		return frame.stackIndex(name);
+	private Sym getSym(String name) {
+		return frame.getSym(name);
 	}
 
 	private void popSymbols(int n) {
-		List<String> symbols = frame.symbols;
+		List<LocalSym> symbols = frame.symbols;
 		while( n-- > 0 ) {
 			symbols.remove(symbols.size()-1);
 		}
 	}
 
-	private int upValueIndex(String name) {
-		return frame.upValueIndex(name);
-	}
-
 	private void incLoops() {
 		frame.loops++;
 	}
@@ -177,13 +244,13 @@
 	private Class newFnClass(int start,StmtString stmt) {
 		if( !stmt.hasReturn )
 			stmt.list.add( "return LuanFunction.NOTHING;\n" );
-		return toFnClass( stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) );
+		return toFnClass( stmt, frame.upValueSymbols );
 	}
 
 	private ExpString newFnExpStr(int start,StmtString stmt) {
 		if( !stmt.hasReturn )
 			stmt.list.add( "return LuanFunction.NOTHING;\n" );
-		return toFnExpStr( stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) );
+		return toFnExpStr( stmt, frame.upValueSymbols );
 	}
 
 	Class Expression() throws ParseException {
@@ -191,12 +258,11 @@
 		int start = parser.begin();
 		ExpString expr = ExprZ(In.NOTHING);
 		if( expr != null && parser.endOfInput() ) {
-			StmtString stmt = new StmtString();
-			stmt.list.add( "return " );
-			stmt.list.addAll( expr.list );
-			stmt.list.add( ";\n" );
-			stmt.hasReturn = true;
-			return parser.success(newFnClass(start,stmt));
+			top.list.add( "return " );
+			top.list.addAll( expr.list );
+			top.list.add( ";\n" );
+			top.hasReturn = true;
+			return parser.success(newFnClass(start,top));
 		}
 		return parser.failure(null);
 	}
@@ -205,9 +271,12 @@
 		Spaces(In.NOTHING);
 		int start = parser.begin();
 		frame.isVarArg = true;
-		StmtString stmt = RequiredBlock();
+		top.list.add( "final Object[] varArgs = LuanImpl.varArgs(args,0);\n" );
+		StmtString block = RequiredBlock();
+		top.list.addAll( block.list );
+		top.hasReturn = block.hasReturn;
 		if( parser.endOfInput() )
-			return parser.success(newFnClass(start,stmt));
+			return parser.success(newFnClass(start,top));
 		throw parser.exception();
 	}
 
@@ -223,17 +292,6 @@
 			Spaces(In.NOTHING);
 		int stackEnd = symbolsSize();
 		popSymbols( stackEnd - stackStart );
-		if( stmts.list.isEmpty() )
-			return stmts;
-		String code = stmts.toString();
-		if( stackStart < stackEnd ) {
-			stmts.list.add( 0, "try {\n" );
-			stmts.list.add( ""
-				+"} finally {\n"
-				+"	luan.stackClear("+stackStart+","+stackEnd+");\n"
-				+"}\n"
-			);
-		}
 		stmts.hasReturn = isReturn;
 		return stmts;
 	}
@@ -260,14 +318,13 @@
 	}
 
 	private boolean Stmt(StmtString stmts) throws ParseException {
-		if( LocalStmt(stmts) )
-			return false;
 		StmtString stmt;
 		if( (stmt=ReturnStmt()) != null ) {
 			stmts.list.addAll(stmt.list);
 			return true;
 		}
 		if( (stmt=FunctionStmt()) != null
+			|| (stmt=LocalStmt()) != null
 			|| (stmt=LocalFunctionStmt()) != null
 			|| (stmt=BreakStmt()) != null
 			|| (stmt=ForStmt()) != null
@@ -387,15 +444,19 @@
 		parser.begin();
 		if( !(Keyword("local",In.NOTHING) && Keyword("function",In.NOTHING)) )
 			return parser.failure(null);
+		StmtString stmt = new StmtString();
 		String name = RequiredName(In.NOTHING);
-		addSymbol( name );
+		addSymbol( name, stmt );
 		ExpString fnDef = RequiredFunction(In.NOTHING);
+		stmt.list.addAll( nameVar(name).set( fnDef ).list );
+/*
 		Settable s = new SetLocalVar(symbolsSize()-1);
 		StmtString stmt = new StmtString();
 		stmt.list.add( settableToString(s) );
 		stmt.list.add( ".set(luan," );
 		stmt.list.addAll( fnDef.list );
 		stmt.list.add( ");\n" );
+*/
 		return parser.success( stmt );
 	}
 
@@ -423,41 +484,30 @@
 		ExpString expr = RequiredExpr(In.NOTHING).expr();
 		RequiredKeyword("do",In.NOTHING);
 
-		SetLocalVar[] vars = new SetLocalVar[names.size()];
-		for( int i=0; i<vars.length; i++ ) {
-			vars[i] = new SetLocalVar(stackStart+i);
-		}
-		String varsStr = varsToString(vars);
-
-		ExpString firstVar = new ExpString(new GetLocalVar(stackStart));
-		addSymbols(names);
-		StmtString loop = RequiredLoopBlock();
-		RequiredKeyword("end",In.NOTHING);
 		String fnVar = "fn"+ ++forCounter;
+		ExpString fnExp = new ExpString(false,false);
+		fnExp.list.add( fnVar + ".call(luan)" );
 		StmtString stmt = new StmtString();
 		stmt.list.add( ""
-			+"try {\n"
 			+"LuanFunction "+fnVar+" = Luan.checkFunction("
 		);
 		stmt.list.addAll( expr.list );
-		stmt.list.add( ""
-			+ ");\n"
-			+"while(true) {\n"
-			+"for( int i="+stackStart+"; i<"+symbolsSize()+"; i++ ) {\n"
-			+"luan.stackSet(i,null);\n"
-			+"}\n"
-			+"LuanImpl.set(luan," + varsStr + ", "+fnVar+".call(luan) );\n"
-			+"if( "
-		);
+		stmt.list.add( ");\n" );
+		stmt.list.add( "while(true) {\n" );
+		List<Var> vars = new ArrayList<Var>();
+		for( String name : names ) {
+			addSymbol(name, stmt);
+			vars.add(nameVar(name));
+		}
+		ExpString firstVar = vars.get(0).exp();
+		stmt.list.addAll( makeSetStmt(vars,fnExp).list );
+		stmt.list.add( "if( " );
 		stmt.list.addAll( firstVar.list );
  		stmt.list.add( "==null )  break;\n" );
+		StmtString loop = RequiredLoopBlock();
+		RequiredKeyword("end",In.NOTHING);
 		stmt.list.addAll( loop.list );
-		stmt.list.add( ""
-			+"}"
-			+"} finally {\n"
-			+"luan.stackClear("+stackStart+","+symbolsSize()+");\n"
-			+"}\n"
-		);
+		stmt.list.add( "}\n" );
 		popSymbols( symbolsSize() - stackStart );
 		return parser.success(stmt);
 	}
@@ -471,33 +521,30 @@
 		return parser.success(stmt);
 	}
 
-	private boolean LocalStmt(StmtString stmts) throws ParseException {
+	private StmtString LocalStmt() throws ParseException {
 		parser.begin();
 		if( !Keyword("local",In.NOTHING) )
-			return parser.failure();
+			return parser.failure(null);
 		List<String> names = NameList(In.NOTHING);
 		if( names==null ) {
 			if( Keyword("function",In.NOTHING) )
-				return parser.failure();  // handled later
+				return parser.failure(null);  // handled later
 			throw parser.exception("Invalid local statement");
 		}
+		StmtString stmt = new StmtString();
+		addSymbols(names,stmt);
 		if( parser.match( '=' ) ) {
 			Spaces(In.NOTHING);
 			ExpString values = ExpStringList(In.NOTHING);
 			if( values==null )
 				throw parser.exception("Expressions expected");
-			SetLocalVar[] vars = new SetLocalVar[names.size()];
-			int stackStart = symbolsSize();
-			for( int i=0; i<vars.length; i++ ) {
-				vars[i] = new SetLocalVar(stackStart+i);
+			List<Var> vars = new ArrayList<Var>();
+			for( String name : names ) {
+				vars.add(nameVar(name));
 			}
-			String varsStr = varsToString(vars);
-			stmts.list.add( "LuanImpl.set(luan," + varsStr + "," );
-			stmts.list.addAll( values.list );
-			stmts.list.add( ");\n" );
+			stmt.list.addAll( makeSetStmt(vars,values).list );
 		}
-		addSymbols(names);
-		return parser.success();
+		return parser.success(stmt);
 	}
 
 	private List<String> RequiredNameList(In in) throws ParseException {
@@ -625,14 +672,18 @@
 		if( values==null )
 //			throw parser.exception("Expressions expected");
 			return parser.failure(null);
+		return parser.success( makeSetStmt(vars,values) );
+	}
+
+	private StmtString makeSetStmt(List<Var> vars,ExpString values) throws ParseException {
 		int n = vars.size();
 		if( n == 1 )
-			return parser.success( vars.get(0).set(values) );
+			return vars.get(0).set(values);
 		StmtString stmt = new StmtString();
 		stmt.list.add( "t = " );
 		stmt.list.addAll( values.list );
 		stmt.list.add( ";\n" );
-		ExpString t = new ExpString(true,false);
+		ExpString t = new ExpString(values.isExpr,false);
 		t.list.add( "t" );
 		stmt.list.addAll( vars.get(0).set(t).list );
 		for( int i=1; i<n; i++ ) {
@@ -640,9 +691,9 @@
 			t.list.add( "LuanImpl.pick(t,"+i+")" );
 			stmt.list.addAll( vars.get(i).set(t).list );
 		}
-		return parser.success( stmt );
+		return stmt;
 	}
-
+/*
 	private static String varsToString(Settable[] vars) {
 		StringBuilder sb = new StringBuilder();
 		sb.append( "new Settable[]{" );
@@ -652,7 +703,7 @@
 		sb.append( "}" );
 		return sb.toString();
 	}
-
+*/
 	private StmtString ExpressionsStmt() throws ParseException {
 		parser.begin();
 		ExpString exp = ExprZ(In.NOTHING);
@@ -969,15 +1020,15 @@
 
 	private ExpString SingleExpr(In in) throws ParseException {
 		parser.begin();
-		ExpString es = FunctionExpr(in);
-		if( es != null )
-			return parser.success(es);
-		es = VarExp(in);
-		if( es != null )
-			return parser.success(es);
-		Expressions exp = VarArgs(in);
+		ExpString exp = FunctionExpr(in);
+		if( exp != null )
+			return parser.success(exp);
+		exp = VarExp(in);
 		if( exp != null )
-			return parser.success(new ExpString(exp));
+			return parser.success(exp);
+		exp = VarArgs(in);
+		if( exp != null )
+			return parser.success(exp);
 		return parser.failure(null);
 	}
 
@@ -993,35 +1044,49 @@
 		In inParens = in.parens();
 		Spaces(inParens);
 		frame = new Frame(frame);
+		StmtString stmt = new StmtString();
 		List<String> names = NameList(in);
 		if( names != null ) {
-			addSymbols(names);
+			addSymbols(names,stmt);
+			List<Var> vars = new ArrayList<Var>();
+			for( String name : names ) {
+				vars.add(nameVar(name));
+			}
+			ExpString args = new ExpString(false,false);
+			args.list.add( "args" );
+			stmt.list.addAll( makeSetStmt(vars,args).list );
 			if( parser.match(',') ) {
 				Spaces(inParens);
 				if( !parser.match("...") )
 					throw parser.exception();
 				Spaces(inParens);
 				frame.isVarArg = true;
+				stmt.list.add( "final Object[] varArgs = LuanImpl.varArgs(args," + vars.size() + ");\n" );
 			}
 		} else if( parser.match("...") ) {
 			Spaces(inParens);
 			frame.isVarArg = true;
+			stmt.list.add( "final Object[] varArgs = LuanImpl.varArgs(args,0);\n" );
 		}
 		RequiredMatch(')');
 		Spaces(in);
 		StmtString block = RequiredBlock();
+		stmt.list.addAll( block.list );
+		stmt.hasReturn = block.hasReturn;
 		RequiredKeyword("end",in);
-		ExpString fnDef = newFnExpStr(start,block);
+		ExpString fnDef = newFnExpStr(start,stmt);
 		frame = frame.parent;
 		return parser.success(fnDef);
 	}
 
-	private VarArgs VarArgs(In in) throws ParseException {
+	private ExpString VarArgs(In in) throws ParseException {
 		parser.begin();
 		if( !frame.isVarArg || !parser.match("...") )
 			return parser.failure(null);
 		Spaces(in);
-		return parser.success( new VarArgs() );
+		ExpString exp = new ExpString(false,false);
+		exp.list.add("varArgs");
+		return parser.success(exp);
 	}
 
 	private ExpString TableExpr(In in) throws ParseException {
@@ -1142,13 +1207,10 @@
 		public StmtString set(ExpString val) throws ParseException;
 	}
 
-	private Expr env() {
-		int index = stackIndex(_ENV);
-		if( index != -1 )
-			return new GetLocalVar(index);
-		index = upValueIndex(_ENV);
-		if( index != -1 )
-			return new GetUpVar(index);
+	private ExpString env() {
+		Sym sym = getSym("_ENV");
+		if( sym != null )
+			return sym.exp();
 		return null;
 	}
 
@@ -1156,15 +1218,12 @@
 		return new Var() {
 
 			public ExpString exp() throws ParseException {
-				int index = stackIndex(name);
-				if( index != -1 )
-					return new ExpString(new GetLocalVar(index));
-				index = upValueIndex(name);
-				if( index != -1 )
-					return new ExpString(new GetUpVar(index));
-				Expr envExpr = env();
+				Sym sym = getSym(name);
+				if( sym != null )
+					return sym.exp();
+				ExpString envExpr = env();
 				if( envExpr != null )
-					return indexExpStr( new ExpString(envExpr), constExpStr(name) );
+					return indexExpStr( envExpr, constExpStr(name) );
 				parser.failure(null);
 				throw parser.exception("name '"+name+"' not defined");
 			}
@@ -1172,7 +1231,7 @@
 			public boolean isSettable() {
 				return true;
 			}
-
+/*
 			private Settable settable() throws ParseException {
 				int index = stackIndex(name);
 				if( index != -1 )
@@ -1186,13 +1245,21 @@
 				parser.failure(null);
 				throw parser.exception("name '"+name+"' not defined");
 			}
-
+*/
 			public StmtString set(ExpString val) throws ParseException {
-				StmtString stmt = new StmtString();
-				stmt.list.add( settableToString(settable()) + ".set(luan," );
-				stmt.list.addAll( val.expr().list );
-				stmt.list.add( ");\n" );
-				return stmt;
+				Sym sym = getSym(name);
+				if( sym != null ) {
+					StmtString stmt = new StmtString();
+					stmt.list.addAll( sym.exp().list );
+					stmt.list.add( " = " );
+					stmt.list.addAll( val.expr().list );
+					stmt.list.add( ";\n" );
+					return stmt;
+				}
+				ExpString envExpr = env();
+				if( envExpr != null )
+					return indexVar( envExpr, constExpStr(name) ).set(val);
+				throw new RuntimeException();
 			}
 		};
 	}
@@ -1699,7 +1766,7 @@
 		final List list = new ArrayList();
 		final boolean isExpr;
 		final boolean isStmt;
-
+/*
 		ExpString(Expressions exp) {
 			if( exp==null )  throw new NullPointerException();
 			int i = LuanImpl.addObj(exp);
@@ -1707,7 +1774,7 @@
 			isExpr = exp instanceof Expr;
 			isStmt = exp instanceof StmtExp;
 		}
-
+*/
 		ExpString(boolean isExpr,boolean isStmt) {
 			this.isExpr = isExpr;
 			this.isStmt = isStmt;
@@ -1770,45 +1837,49 @@
 		return sb.toString();
 	}
 
-	private static Class toFnClass(StmtString stmt,int stackSize,int numArgs,boolean isVarArg,UpValue.Getter[] upValueGetters) {
+	private Class toFnClass(StmtString stmt,List<UpSym> upValueSymbols) {
 		String code = concat(stmt.list);
 //System.out.println("code:\n"+code);
 
-		int i = LuanImpl.addObj(upValueGetters);
 		String className = "EXP" + ++classCounter;
 		String classCode = ""
 			+"package luan.impl;\n"
 			+"import luan.Luan;\n"
 			+"import luan.LuanFunction;\n"
+			+"import luan.LuanState;\n"
 			+"import luan.LuanException;\n"
 			+"import luan.modules.PackageLuan;\n"
 			+"\n"
 			+"public class " + className +" extends Closure {\n"
-			+"	public "+className+"(LuanStateImpl luan) throws LuanException {\n"
-			+"		super(luan,"+stackSize+","+numArgs+","+isVarArg+",(UpValue.Getter[])LuanImpl.getObj("+i+"));\n"
+			+"	public "+className+"(LuanState luan) throws LuanException {\n"
+			+"		super("+upValueSymbols.size()+");\n"
+			+		init(upValueSymbols)
 			+"	}\n"
 			+"\n"
-			+"	@Override public Object run(LuanStateImpl luan) throws LuanException {\n"
+			+"	@Override public Object doCall(LuanState luan,Object[] args) throws LuanException {\n"
 			+"		Object t;\n"
 			+"		" + code
 			+"	}\n"
 			+"}\n"
 		;
 		try {
-//System.out.println(classCode);
-			return LuanJavaCompiler.compile("luan.impl."+className,"code",classCode);
+System.out.println(parser.sourceName);
+System.out.println(classCode);
+			return LuanJavaCompiler.compile("luan.impl."+className,parser.sourceName,classCode);
 		} catch(ClassNotFoundException e) {
 			throw new RuntimeException(e);
 		}
 	}
 
-	private ExpString toFnExpStr(StmtString stmt,int stackSize,int numArgs,boolean isVarArg,UpValue.Getter[] upValueGetters) {
-		int i = LuanImpl.addObj(upValueGetters);
+	private ExpString toFnExpStr(StmtString stmt,List<UpSym> upValueSymbols) {
 		ExpString exp = new ExpString(true,false);
 		exp.list.add( ""
 			+"\n"
-			+"new Closure(luan,"+stackSize+","+numArgs+","+isVarArg+",(UpValue.Getter[])LuanImpl.getObj("+i+")) {\n"
-			+"	@Override public Object run(LuanStateImpl luan) throws LuanException {\n"
+			+"new Closure("+upValueSymbols.size()+") {\n"
+			+"{\n"
+			+ init(upValueSymbols)
+			+"}\n"
+			+"	@Override public Object doCall(LuanState luan,Object[] args) throws LuanException {\n"
 			+"		Object t;\n"
 			+"		"
 		);
@@ -1820,11 +1891,19 @@
 		return exp;
 	}
 
+	private static String init(List<UpSym> upValueSymbols) {
+		StringBuilder sb = new StringBuilder();
+		for( UpSym upSym : upValueSymbols ) {
+			sb.append( upSym.init() );
+		}
+		return sb.toString();
+	}
 
+/*
 	private static String settableToString(Settable settable) {
 		if( settable==null )  throw new NullPointerException();
 		int i = LuanImpl.addObj(settable);
 		return"((Settable)LuanImpl.getObj(" + i + "))";
 	}
-
+*/
 }
--- a/core/src/luan/impl/LuanStateImpl.java	Mon Apr 11 16:00:44 2016 -0600
+++ b/core/src/luan/impl/LuanStateImpl.java	Tue Apr 12 01:05:57 2016 -0600
@@ -13,46 +13,7 @@
 
 
 public final class LuanStateImpl extends LuanState {
-
-	private static class Frame {
-		final Frame previousFrame;
-		final Closure closure;
-		final Object[] stack;
-		final Object[] varArgs;
-		UpValue[] downValues = null;
-
-		Frame( Frame previousFrame, Closure closure, int stackSize, Object[] varArgs) {
-			this.previousFrame = previousFrame;
-			this.closure = closure;
-			this.stack = new Object[stackSize];
-			this.varArgs = varArgs;
-		}
-
-		void stackClear(int start,int end) {
-			if( downValues != null ) {
-				for( int i=start; i<end; i++ ) {
-					UpValue downValue = downValues[i];
-					if( downValue != null ) {
-						downValue.close();
-						downValues[i] = null;
-					}
-				}
-			}
-			for( int i=start; i<end; i++ ) {
-				stack[i] = null;
-			}
-		}
-
-		UpValue getUpValue(int index) {
-			if( downValues==null )
-				downValues = new UpValue[stack.length];
-			if( downValues[index] == null )
-				downValues[index] = new UpValue(stack,index);
-			return downValues[index];
-		}
-	}
-
-	private Frame frame = null;
+	Closure closure;
 
 	LuanStateImpl() {}
 
@@ -61,54 +22,17 @@
 	}
 
 	@Override public LuanState shallowClone() {
-//		if( frame != null )
-//			throw new IllegalStateException("frame isn't null");
 		return new LuanStateImpl(this);
 	}
 
-	// returns stack
-	Object[] newFrame(Closure closure, int stackSize, Object[] varArgs) {
-		frame = new Frame(frame,closure,stackSize,varArgs);
-		return frame.stack;
-	}
-
-	void popFrame() {
-		frame = frame.previousFrame;
-	}
-
-	Object stackGet(int index) {
-		return frame.stack[index];
-	}
-
-	public void stackSet(int index,Object value) {
-		frame.stack[index] = value;
-	}
-
-	public void stackClear(int start,int end) {
-		frame.stackClear(start,end);
-	}
-
-	Object[] varArgs() {
-		return frame.varArgs;
-	}
-
-	Closure closure() {
-		return frame.closure;
-	}
-
-	UpValue getUpValue(int index) {
-		return frame.getUpValue(index);
-	}
-
 	@Override public boolean hasJava() {
-		if( frame==null )
+		if( closure==null )
 			return false;
-		return ((LuanTable)frame.closure.upValues()[0].get()).hasJava;
+		return ((LuanTable)closure.upValues[0].o).hasJava;
 	}
 
 	@Override public void setJava() {
-		((LuanTable)frame.closure.upValues()[0].get()).hasJava = true;
+		((LuanTable)closure.upValues[0].o).hasJava = true;
 	}
 
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/src/luan/impl/Pointer.java	Tue Apr 12 01:05:57 2016 -0600
@@ -0,0 +1,17 @@
+package luan.impl;
+
+import luan.DeepCloneable;
+import luan.DeepCloner;
+
+
+public final class Pointer implements DeepCloneable {
+	public Object o;
+
+	@Override public Pointer shallowClone() {
+		return new Pointer();
+	}
+
+	@Override public void deepenClone(DeepCloneable clone,DeepCloner cloner) {
+		((Pointer)clone).o = cloner.get(o);
+	}
+}
--- a/core/src/luan/impl/SetLocalVar.java	Mon Apr 11 16:00:44 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-package luan.impl;
-
-
-final class SetLocalVar implements Settable {
-	private final int index;
-
-	SetLocalVar(int index) {
-		if( index < 0 )  throw new RuntimeException();
-		this.index = index;
-	}
-
-	@Override public void set(LuanStateImpl luan,Object value) {
-		luan.stackSet( index, value );
-	}
-}
--- a/core/src/luan/impl/SetUpVar.java	Mon Apr 11 16:00:44 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-package luan.impl;
-
-
-final class SetUpVar implements Settable {
-	private final int index;
-
-	SetUpVar(int index) {
-		this.index = index;
-	}
-
-	@Override public void set(LuanStateImpl luan,Object value) {
-		luan.closure().upValues()[index].set(value);
-	}
-}
--- a/core/src/luan/impl/ThemeParser.java	Mon Apr 11 16:00:44 2016 -0600
+++ b/core/src/luan/impl/ThemeParser.java	Tue Apr 12 01:05:57 2016 -0600
@@ -27,7 +27,7 @@
 */
 		return null;
 	}
-
+/*
 	private static final class Frame {
 		final Frame parent;
 		final List<String> symbols = new ArrayList<String>();
@@ -110,7 +110,7 @@
 	}
 
 	private Class newFnDef(Stmt stmt) {
-//		return new FnDef( /*stmt*/null, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) );
+//		return new FnDef( stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) );
 		return null;
 	}
 
@@ -191,7 +191,7 @@
 		Stmt block = parseBody("define:"+name,spaces,indent);
 		Class fnDef = newFnDef(block);
 		frame = frame.parent;
-		Stmt rtn = new SetStmt(fnName,/*fnDef*/null);
+		Stmt rtn = new SetStmt(fnName,fnDef);
 		return parser.success(rtn);
 	}
 
@@ -273,7 +273,7 @@
 /*
 		if( tagName.startsWith("define:") )
 			EndOfLine();
-*/
+* /
 		if( EndOfLine() )
 			InlineSpaces();
 		return parser.match("{/") && parser.match(tagName) && parser.match('}') ? parser.success() : parser.failure();
@@ -339,7 +339,7 @@
 		Expr fn = new IndexExpr( env, new ConstExpr(name) );
 		List<Expressions> args = new ArrayList<Expressions>();
 		args.add( env );
-		args.add( /*fnDef*/null );
+		args.add( fnDef );
 		FnCall fnCall = new FnCall( fn, ExpList.build(args) );
 		Stmt rtn = new ExpressionsStmt(fnCall);
 		return parser.success(rtn);
@@ -410,5 +410,5 @@
 		return parser.inCharRange('a', 'z') || parser.inCharRange('A', 'Z')
 			|| parser.inCharRange('0', '9') || parser.anyOf("-_.");
 	}
-
+*/
 }
--- a/core/src/luan/impl/UpValue.java	Mon Apr 11 16:00:44 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-package luan.impl;
-
-import luan.DeepCloner;
-import luan.DeepCloneable;
-import luan.LuanException;
-
-
-public final class UpValue implements DeepCloneable {
-	private Object[] stack;
-	private int index;
-	private boolean isClosed = false;
-	private Object value;
-
-	UpValue(Object[] stack,int index) {
-		this.stack = stack;
-		this.index = index;
-	}
-
-	UpValue(Object value) {
-		this.value = value;
-		this.isClosed = true;
-	}
-
-	private UpValue() {}
-
-	@Override public UpValue shallowClone() {
-		return new UpValue();
-	}
-
-	@Override public void deepenClone(DeepCloneable dc,DeepCloner cloner) {
-		UpValue clone = (UpValue)dc;
-		clone.isClosed = isClosed;
-		if( isClosed ) {
-			clone.value = cloner.get(value);
-		} else {
-			clone.stack = cloner.deepClone(stack);
-			clone.index = index;
-		}
-	}
-
-	Object get() {
-		return isClosed ? value : stack[index];
-	}
-
-	void set(Object value) {
-		if( isClosed ) {
-			this.value = value;
-		} else {
-			stack[index] = value;
-		}
-	}
-
-	void close() {
-		value = stack[index];
-		isClosed = true;
-		stack = null;
-	}
-
-	public static interface Getter {
-		public UpValue get(LuanStateImpl luan) throws LuanException;
-	}
-
-	static final class StackGetter implements Getter {
-		private final int index;
-
-		StackGetter(int index) {
-			this.index = index;
-		}
-
-		public UpValue get(LuanStateImpl luan) {
-			return luan.getUpValue(index);
-		}
-	}
-
-	static final class NestedGetter implements Getter {
-		private final int index;
-
-		NestedGetter(int index) {
-			this.index = index;
-		}
-
-		public UpValue get(LuanStateImpl luan) {
-			return luan.closure().upValues()[index];
-		}
-	}
-
-	static final class ValueGetter implements Getter {
-		private final UpValue upValue;
-
-		ValueGetter(Object value) {
-			this.upValue = new UpValue(value);
-		}
-
-		public UpValue get(LuanStateImpl luan) {
-			return upValue;
-		}
-	}
-
-}
--- a/core/src/luan/impl/VarArgs.java	Mon Apr 11 16:00:44 2016 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-package luan.impl;
-
-
-final class VarArgs extends CodeImpl implements Expressions {
-
-	@Override public Object[] eval(LuanStateImpl luan) {
-		return luan.varArgs();
-	}
-}