diff src/luan/interp/ReturnStmt.java @ 22:1e37f22a34c8

proper tail calls git-svn-id: https://luan-java.googlecode.com/svn/trunk@23 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Wed, 05 Dec 2012 09:03:50 +0000
parents c93d8c781853
children 5cf15507d77e
line wrap: on
line diff
--- a/src/luan/interp/ReturnStmt.java	Tue Dec 04 09:16:03 2012 +0000
+++ b/src/luan/interp/ReturnStmt.java	Wed Dec 05 09:03:50 2012 +0000
@@ -1,19 +1,38 @@
 package luan.interp;
 
+import luan.Lua;
 import luan.LuaState;
 import luan.LuaException;
+import luan.LuaFunction;
+import luan.LuaClosure;
 
 
 final class ReturnStmt implements Stmt {
 	private final Expressions expressions;
+	private final Expr tailFnExpr;
 	boolean throwReturnException = true;
 
 	ReturnStmt(Expressions expressions) {
-		this.expressions = expressions;
+		if( expressions instanceof FnCall ) {  // tail call
+			FnCall fnCall = (FnCall)expressions;
+			this.expressions = fnCall.args;
+			this.tailFnExpr = fnCall.fnExpr;
+		} else {
+			this.expressions = expressions;
+			this.tailFnExpr = null;
+		}
 	}
 
 	@Override public void eval(LuaState lua) throws LuaException {
 		lua.returnValues = expressions.eval(lua);
+		if( tailFnExpr != null ) {
+			LuaFunction tailFn = Lua.checkFunction( tailFnExpr.eval(lua) );
+			if( tailFn instanceof LuaClosure ) {
+				lua.tailFn = (LuaClosure)tailFn;
+			} else {
+				lua.returnValues =  tailFn.call(lua,lua.returnValues);
+			}
+		}
 		if( throwReturnException )
 			throw new ReturnException();
 	}