Fix to tailcall processing.

This commit is contained in:
James Roseborough
2010-04-20 00:37:23 +00:00
parent 8bd255a356
commit 19f8a2d372
6 changed files with 40 additions and 11 deletions

View File

@@ -101,6 +101,10 @@ public class LuaClosure extends LuaFunction {
}
public final Varargs invoke(Varargs varargs) {
return oninvoke( varargs ).eval();
}
final Varargs oninvoke(Varargs varargs) {
LuaValue[] stack = new LuaValue[p.maxstacksize];
System.arraycopy(NILS, 0, stack, 0, p.maxstacksize);
for ( int i=0; i<p.numparams; i++ )
@@ -108,6 +112,7 @@ public class LuaClosure extends LuaFunction {
return execute(stack,p.is_vararg!=0? varargs.subargs(p.numparams+1): NONE);
}
protected Varargs execute( LuaValue[] stack, Varargs varargs ) {
// loop through instructions
int i,a,b,c,pc=0,top=0;

View File

@@ -71,6 +71,20 @@ public class LuaError extends RuntimeException {
public LuaError(String message) {
super( errorHook( message ) );
}
/**
* @param message message to supply
* @param level where to supply line info from in call stack
*/
public LuaError(String message, int level) {
super( errorHook( addFileLine( message, level ) ) );
}
/** Add file and line info to a message */
private static String addFileLine( String message, int level ) {
LuaFunction f = LuaThread.getCallstackFunction(level);
return f!=null? f+": "+message: message;
}
/** Get the message, including source line info if there is any */
public String getMessage() {

View File

@@ -32,13 +32,15 @@ public class TailcallVarargs extends Varargs {
this.args = args;
}
private void eval() {
public Varargs eval() {
TailcallVarargs nextcall = this;
do {
LuaValue func = nextcall.func;
Varargs args = nextcall.args;
nextcall = null;
Varargs r = func.invoke(args);
Varargs r = func.isclosure()?
((LuaClosure) func).oninvoke(args):
func.invoke(args);
if (r instanceof TailcallVarargs)
nextcall = (TailcallVarargs)r;
@@ -46,6 +48,7 @@ public class TailcallVarargs extends Varargs {
this.result = r;
} while (nextcall != null);
return result;
}
public LuaValue arg( int i ) {

View File

@@ -45,6 +45,12 @@ public abstract class Varargs {
* @return Value
*/
abstract public LuaValue arg1();
/**
* Evaluate any pending tail call and return result
* @return the evaluated tail call result
*/
public Varargs eval() { return this; }
// -----------------------------------------------------------------------
// utilities to get specific arguments and type-check them.

View File

@@ -26,7 +26,6 @@ import java.io.PrintStream;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaThread;
@@ -162,7 +161,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
}
return NIL;
case 1: // "error", // ( message [,level] ) -> ERR
throw new LuaError( arg1.isnil()? null: arg1.toString() );
throw new LuaError( arg1.isnil()? null: arg1.toString(), arg2.optint(1) );
case 2: // "rawequal", // (v1, v2) -> boolean
return valueOf(arg1 == arg2);
case 3: { // "setfenv", // (f, table) -> void
@@ -347,7 +346,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
return NONE;
}
private Varargs loadFile(String filename) throws IOException {
public static Varargs loadFile(String filename) throws IOException {
InputStream is = FINDER.findResource(filename);
if ( is == null )
return varargsOf(NIL, valueOf("not found: "+filename));

View File

@@ -21,6 +21,7 @@
******************************************************************************/
package org.luaj.vm2.lib;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
@@ -306,11 +307,6 @@ public class PackageLib extends OneArgFunction {
String name = args.checkString(1);
InputStream is = null;
// try to use loadfile for the file
LuaValue loadfile = env.get(_LOADFILE);
if ( ! loadfile.isfunction() )
return valueOf("loadfile is not a function" );
// get package path
LuaValue pp = PACKAGE.get(_PATH);
@@ -340,7 +336,13 @@ public class PackageLib extends OneArgFunction {
}
// try loading the file
Varargs v = loadfile.invoke(valueOf(filename));
Varargs v;
try {
v = BaseLib.loadFile(filename);
} catch ( IOException ioe ) {
v = varargsOf(NIL, valueOf(ioe.getMessage()));
}
if ( v.arg1().isfunction() )
return v.arg1();