Add "Java API" like "C API" for use with JavaFunctions.

This commit is contained in:
James Roseborough
2007-10-04 23:51:39 +00:00
parent 9be13fcc1d
commit e4882578f2
8 changed files with 1392 additions and 117 deletions

View File

@@ -219,7 +219,7 @@ public class LuaCompat extends LFunction {
if ( t instanceof LTable ) {
( (LTable) t ).put( k, v );
} else {
vm.lua_error( "expected table" );
vm.error( "expected table" );
}
} break;
case SETFENV:
@@ -478,8 +478,8 @@ public class LuaCompat extends LFunction {
private static boolean loadis(VM vm, InputStream is, String chunkname ) {
try {
vm.setResult();
if ( 0 != vm.lua_load(is, chunkname) ) {
vm.setErrorResult( LNil.NIL, "cannot load "+chunkname+": "+vm.lua_tolvalue(-1) );
if ( 0 != vm.load(is, chunkname) ) {
vm.setErrorResult( LNil.NIL, "cannot load "+chunkname+": "+vm.topointer(-1) );
return false;
} else {
return true;
@@ -515,10 +515,10 @@ public class LuaCompat extends LFunction {
private void dofile( VM vm ) {
String filename = vm.getArgAsString(0);
if ( loadfile( vm, filename ) ) {
int s = vm.lua_pcall(1, 0);
int s = vm.pcall(1, 0, 0);
vm.setResult( LInteger.valueOf( s!=0? 1: 0 ) );
} else {
vm.lua_error("cannot open "+filename);
vm.error("cannot open "+filename);
}
}
@@ -532,7 +532,7 @@ public class LuaCompat extends LFunction {
// return true if loaded, false if error put onto stack
private boolean load(VM vm, LValue chunkPartLoader, String chunkname) {
if ( ! (chunkPartLoader instanceof Closure) ) {
vm.lua_error("not a closure: "+chunkPartLoader);
vm.error("not a closure: "+chunkPartLoader);
}
// load all the parts
@@ -541,7 +541,7 @@ public class LuaCompat extends LFunction {
try {
while ( true ) {
vm.setResult(c);
if ( 0 != vm.lua_pcall(0, 1) ) {
if ( 0 != vm.pcall(0, 1, 0) ) {
vm.setErrorResult(LNil.NIL, vm.getArgAsString(0));
return false;
}
@@ -599,7 +599,7 @@ public class LuaCompat extends LFunction {
// ======================== Module, Package loading =============================
public static void module( VM vm ) {
vm.lua_error( "module not implemented" );
vm.error( "module not implemented" );
}
/**
@@ -635,9 +635,9 @@ public class LuaCompat extends LFunction {
else {
String s = modname.toJavaString();
if ( ! loadfile(vm, s+".luac") && ! loadfile(vm, s+".lua") )
vm.lua_error( "not found: "+s );
else if ( 0 == vm.lua_pcall(0, 1) ) {
LValue result = vm.lua_tolvalue( -1 );
vm.error( "not found: "+s );
else if ( 0 == vm.pcall(0, 1, 0) ) {
LValue result = vm.topointer( -1 );
if ( result != LNil.NIL )
LOADED.put(modname, result);
else if ( ! LOADED.containsKey(modname) )
@@ -648,11 +648,11 @@ public class LuaCompat extends LFunction {
}
public static void loadlib( VM vm ) {
vm.lua_error( "loadlib not implemented" );
vm.error( "loadlib not implemented" );
}
public static void seeall( VM vm ) {
vm.lua_error( "seeall not implemented" );
vm.error( "seeall not implemented" );
}
@@ -683,7 +683,7 @@ public class LuaCompat extends LFunction {
}
vm.setResult( new LString( baos.toByteArray() ) );
} catch (IOException e) {
vm.lua_error(e.getMessage());
vm.error(e.getMessage());
}
}

View File

@@ -68,7 +68,7 @@ public class StrLib {
* TODO: port dumping code as optional add-on
*/
static void dump( VM vm ) {
vm.lua_error("dump() not supported");
vm.error("dump() not supported");
}
/**
@@ -509,8 +509,8 @@ public class StrLib {
lbuf.append( s.substring( soff, e ) );
} else {
push_onecapture( b - '1', soff, e );
lbuf.append( vm.lua_tolvalue( -1 ).luaAsString() );
vm.lua_pop( 1 );
lbuf.append( vm.topointer( -1 ).luaAsString() );
vm.pop( 1 );
}
}
}
@@ -523,25 +523,25 @@ public class StrLib {
} else if ( repl instanceof LFunction ) {
vm.push( repl );
int n = push_captures( true, soffset, end );
vm.lua_call( n, 1 );
vm.call( n, 1 );
} else if ( repl instanceof LTable ) {
// Need to call push_onecapture here for the error checking
push_onecapture( 0, soffset, end );
LValue k = vm.lua_tolvalue( -1 );
vm.lua_pop( 1 );
LValue k = vm.topointer( -1 );
vm.pop( 1 );
((LTable) repl).luaGetTable( vm, repl, k );
} else {
vm.lua_error( "string/function/table expected" );
vm.error( "string/function/table expected" );
return;
}
repl = vm.lua_tolvalue( -1 );
repl = vm.topointer( -1 );
if ( !repl.luaAsBoolean() ) {
repl = s.substring( soffset, end );
} else if ( ! ( repl instanceof LString || repl instanceof LNumber ) ) {
vm.lua_error( "invalid replacement value (a "+repl.luaGetTypeName()+")" );
vm.error( "invalid replacement value (a "+repl.luaGetTypeName()+")" );
}
vm.lua_pop( 1 );
vm.pop( 1 );
lbuf.append( repl.luaAsString() );
}
@@ -558,12 +558,12 @@ public class StrLib {
if ( i == 0 ) {
vm.push( s.substring( soff, end ) );
} else {
vm.lua_error( "invalid capture index" );
vm.error( "invalid capture index" );
}
} else {
int l = clen[i];
if ( l == CAP_UNFINISHED ) {
vm.lua_error( "unfinished capture" );
vm.error( "unfinished capture" );
}
if ( l == CAP_POSITION ) {
vm.push( LInteger.valueOf( cinit[i] + 1 ) );
@@ -577,7 +577,7 @@ public class StrLib {
private int check_capture( int l ) {
l -= '1';
if ( l < 0 || l >= level || this.clen[l] == CAP_UNFINISHED ) {
vm.lua_error("invalid capture index");
vm.error("invalid capture index");
}
return l;
}
@@ -587,7 +587,7 @@ public class StrLib {
for ( level--; level >= 0; level-- )
if ( clen[level] == CAP_UNFINISHED )
return level;
vm.lua_error("invalid pattern capture");
vm.error("invalid pattern capture");
return 0;
}
@@ -595,7 +595,7 @@ public class StrLib {
switch ( p.luaByte( poffset++ ) ) {
case L_ESC:
if ( poffset == p.length() ) {
vm.lua_error( "malformed pattern (ends with %)" );
vm.error( "malformed pattern (ends with %)" );
}
return poffset + 1;
@@ -603,7 +603,7 @@ public class StrLib {
if ( p.luaByte( poffset ) == '^' ) poffset++;
do {
if ( poffset == p.length() ) {
vm.lua_error( "malformed pattern (missing ])" );
vm.error( "malformed pattern (missing ])" );
}
if ( p.luaByte( poffset++ ) == L_ESC && poffset != p.length() )
poffset++;
@@ -695,7 +695,7 @@ public class StrLib {
case 'f': {
poffset += 2;
if ( p.luaByte( poffset ) != '[' ) {
vm.lua_error("Missing [ after %f in pattern");
vm.error("Missing [ after %f in pattern");
}
int ep = classend( poffset );
int previous = ( soffset == 0 ) ? -1 : s.luaByte( soffset - 1 );
@@ -775,7 +775,7 @@ public class StrLib {
int res;
int level = this.level;
if ( level >= MAX_CAPTURES ) {
vm.lua_error( "too many captures" );
vm.error( "too many captures" );
}
cinit[ level ] = soff;
clen[ level ] = what;
@@ -807,7 +807,7 @@ public class StrLib {
int matchbalance( int soff, int poff ) {
final int plen = p.length();
if ( poff == plen || poff + 1 == plen ) {
vm.lua_error( "unbalanced pattern" );
vm.error( "unbalanced pattern" );
}
if ( s.luaByte( soff ) != p.luaByte( poff ) )
return -1;

View File

@@ -78,9 +78,9 @@ final class Builtin extends LFunction {
break;
case PCALL: {
int n = vm.getArgCount();
int s = vm.lua_pcall( n-1, Lua.LUA_MULTRET );
int s = vm.pcall( n-1, Lua.LUA_MULTRET, 0 );
if ( s != 0 ) {
LValue v = vm.lua_tolvalue(-1);
LValue v = vm.topointer(-1);
vm.setResult( LBoolean.FALSE );
vm.push( v );
} else {

View File

@@ -0,0 +1,74 @@
package lua;
import lua.value.LFunction;
/**
Type for Java&nbsp;functions.
<p>
In order to communicate properly with Lua,
a Java&nbsp;function must use the following protocol,
which defines the way parameters and results are passed:
a Java&nbsp;function receives its arguments from Lua in its stack
in direct order (the first argument is pushed first).
So, when the function starts,
<code>lua_gettop(L)</code> returns the number of arguments received by the function.
The first argument (if any) is at index 1
and its last argument is at index <code>lua_gettop(L)</code>.
To return values to Lua, a Java&nbsp;function just pushes them onto the stack,
in direct order (the first result is pushed first),
and returns the number of results.
Any other value in the stack below the results will be properly
discarded by Lua.
Like a Lua function, a Java&nbsp;function called by Lua can also return
many results.
<p>
As an example, the following function receives a variable number
of numerical arguments and returns their average and sum:
<pre><code>
int foo (VM lua) {
int n = lua.gettop(); // number of arguments
double sum = 0;
int i;
for (i = 1; i &lt;= n; i++) {
if (!lua.isnumber(L, i)) {
lua.pushstring(L, "incorrect argument");
lua.error(L);
}
sum += lua.tonumber(L, i);
}
lua.pushnumber(L, sum/n); // first result
lua.pushnumber(L, sum); // second result
return 2; // number of results
}
</code></pre>
*/
abstract public class JavaFunction extends LFunction {
/**
* Called to invoke a JavaFunction.
*
* The implementation should manipulate the stack
* via the VM Java API in the same way that lua_CFunctions
* do so in standard lua.
*
* @param lua the LuaState calling this function.
* @return number of results pushed onto the stack.
*/
abstract public int invoke( VM lua );
/**
* Set up a Java invocation, and fix up the results
* when it returns.
*/
public boolean luaStackCall(VM vm) {
vm.invokeJavaFunction( this );
return true;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -89,8 +89,8 @@ public class DebugStackState extends StackState implements DebugRequestListener
// override and fill in line number info
public void lua_error(String message) {
super.lua_error( getFileLine(cc)+": "+message );
public void error(String message) {
super.error( getFileLine(cc)+": "+message );
}
private void printLuaTrace() {

View File

@@ -15,14 +15,14 @@ public class LFunction extends LValue {
vm.push( table );
vm.push( key );
vm.push( val );
vm.lua_call( 3, 0 );
vm.call( 3, 0 );
}
public void luaGetTable(VM vm, LValue table, LValue key) {
vm.push( this );
vm.push( table );
vm.push( key );
vm.lua_call( 2, 1 );
vm.call( 2, 1 );
}
public int luaGetType() {

View File

@@ -33,7 +33,7 @@ public class LValue {
// perform a lua call, return true if the call is to a lua function, false
// if it ran to completion.
public boolean luaStackCall(VM vm) {
vm.lua_error("attempt to call "+this);
vm.error("attempt to call "+this);
return false;
}