Fix to tailcall processing.
This commit is contained in:
@@ -101,6 +101,10 @@ public class LuaClosure extends LuaFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final Varargs invoke(Varargs varargs) {
|
public final Varargs invoke(Varargs varargs) {
|
||||||
|
return oninvoke( varargs ).eval();
|
||||||
|
}
|
||||||
|
|
||||||
|
final Varargs oninvoke(Varargs varargs) {
|
||||||
LuaValue[] stack = new LuaValue[p.maxstacksize];
|
LuaValue[] stack = new LuaValue[p.maxstacksize];
|
||||||
System.arraycopy(NILS, 0, stack, 0, p.maxstacksize);
|
System.arraycopy(NILS, 0, stack, 0, p.maxstacksize);
|
||||||
for ( int i=0; i<p.numparams; i++ )
|
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);
|
return execute(stack,p.is_vararg!=0? varargs.subargs(p.numparams+1): NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected Varargs execute( LuaValue[] stack, Varargs varargs ) {
|
protected Varargs execute( LuaValue[] stack, Varargs varargs ) {
|
||||||
// loop through instructions
|
// loop through instructions
|
||||||
int i,a,b,c,pc=0,top=0;
|
int i,a,b,c,pc=0,top=0;
|
||||||
|
|||||||
@@ -71,6 +71,20 @@ public class LuaError extends RuntimeException {
|
|||||||
public LuaError(String message) {
|
public LuaError(String message) {
|
||||||
super( errorHook( 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 */
|
/** Get the message, including source line info if there is any */
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
|
|||||||
@@ -32,13 +32,15 @@ public class TailcallVarargs extends Varargs {
|
|||||||
this.args = args;
|
this.args = args;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void eval() {
|
public Varargs eval() {
|
||||||
TailcallVarargs nextcall = this;
|
TailcallVarargs nextcall = this;
|
||||||
do {
|
do {
|
||||||
LuaValue func = nextcall.func;
|
LuaValue func = nextcall.func;
|
||||||
Varargs args = nextcall.args;
|
Varargs args = nextcall.args;
|
||||||
nextcall = null;
|
nextcall = null;
|
||||||
Varargs r = func.invoke(args);
|
Varargs r = func.isclosure()?
|
||||||
|
((LuaClosure) func).oninvoke(args):
|
||||||
|
func.invoke(args);
|
||||||
|
|
||||||
if (r instanceof TailcallVarargs)
|
if (r instanceof TailcallVarargs)
|
||||||
nextcall = (TailcallVarargs)r;
|
nextcall = (TailcallVarargs)r;
|
||||||
@@ -46,6 +48,7 @@ public class TailcallVarargs extends Varargs {
|
|||||||
this.result = r;
|
this.result = r;
|
||||||
|
|
||||||
} while (nextcall != null);
|
} while (nextcall != null);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue arg( int i ) {
|
public LuaValue arg( int i ) {
|
||||||
|
|||||||
@@ -45,6 +45,12 @@ public abstract class Varargs {
|
|||||||
* @return Value
|
* @return Value
|
||||||
*/
|
*/
|
||||||
abstract public LuaValue arg1();
|
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.
|
// utilities to get specific arguments and type-check them.
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import java.io.PrintStream;
|
|||||||
|
|
||||||
import org.luaj.vm2.LoadState;
|
import org.luaj.vm2.LoadState;
|
||||||
import org.luaj.vm2.LuaError;
|
import org.luaj.vm2.LuaError;
|
||||||
import org.luaj.vm2.LuaFunction;
|
|
||||||
import org.luaj.vm2.LuaString;
|
import org.luaj.vm2.LuaString;
|
||||||
import org.luaj.vm2.LuaTable;
|
import org.luaj.vm2.LuaTable;
|
||||||
import org.luaj.vm2.LuaThread;
|
import org.luaj.vm2.LuaThread;
|
||||||
@@ -162,7 +161,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
|||||||
}
|
}
|
||||||
return NIL;
|
return NIL;
|
||||||
case 1: // "error", // ( message [,level] ) -> ERR
|
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
|
case 2: // "rawequal", // (v1, v2) -> boolean
|
||||||
return valueOf(arg1 == arg2);
|
return valueOf(arg1 == arg2);
|
||||||
case 3: { // "setfenv", // (f, table) -> void
|
case 3: { // "setfenv", // (f, table) -> void
|
||||||
@@ -347,7 +346,7 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
|||||||
return NONE;
|
return NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Varargs loadFile(String filename) throws IOException {
|
public static Varargs loadFile(String filename) throws IOException {
|
||||||
InputStream is = FINDER.findResource(filename);
|
InputStream is = FINDER.findResource(filename);
|
||||||
if ( is == null )
|
if ( is == null )
|
||||||
return varargsOf(NIL, valueOf("not found: "+filename));
|
return varargsOf(NIL, valueOf("not found: "+filename));
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.vm2.lib;
|
package org.luaj.vm2.lib;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
@@ -306,11 +307,6 @@ public class PackageLib extends OneArgFunction {
|
|||||||
String name = args.checkString(1);
|
String name = args.checkString(1);
|
||||||
InputStream is = null;
|
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
|
// get package path
|
||||||
LuaValue pp = PACKAGE.get(_PATH);
|
LuaValue pp = PACKAGE.get(_PATH);
|
||||||
@@ -340,7 +336,13 @@ public class PackageLib extends OneArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try loading the file
|
// 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() )
|
if ( v.arg1().isfunction() )
|
||||||
return v.arg1();
|
return v.arg1();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user