Add "Java API" like "C API" for use with JavaFunctions.
This commit is contained in:
@@ -219,7 +219,7 @@ public class LuaCompat extends LFunction {
|
|||||||
if ( t instanceof LTable ) {
|
if ( t instanceof LTable ) {
|
||||||
( (LTable) t ).put( k, v );
|
( (LTable) t ).put( k, v );
|
||||||
} else {
|
} else {
|
||||||
vm.lua_error( "expected table" );
|
vm.error( "expected table" );
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case SETFENV:
|
case SETFENV:
|
||||||
@@ -478,8 +478,8 @@ public class LuaCompat extends LFunction {
|
|||||||
private static boolean loadis(VM vm, InputStream is, String chunkname ) {
|
private static boolean loadis(VM vm, InputStream is, String chunkname ) {
|
||||||
try {
|
try {
|
||||||
vm.setResult();
|
vm.setResult();
|
||||||
if ( 0 != vm.lua_load(is, chunkname) ) {
|
if ( 0 != vm.load(is, chunkname) ) {
|
||||||
vm.setErrorResult( LNil.NIL, "cannot load "+chunkname+": "+vm.lua_tolvalue(-1) );
|
vm.setErrorResult( LNil.NIL, "cannot load "+chunkname+": "+vm.topointer(-1) );
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
@@ -515,10 +515,10 @@ public class LuaCompat extends LFunction {
|
|||||||
private void dofile( VM vm ) {
|
private void dofile( VM vm ) {
|
||||||
String filename = vm.getArgAsString(0);
|
String filename = vm.getArgAsString(0);
|
||||||
if ( loadfile( vm, filename ) ) {
|
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 ) );
|
vm.setResult( LInteger.valueOf( s!=0? 1: 0 ) );
|
||||||
} else {
|
} 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
|
// return true if loaded, false if error put onto stack
|
||||||
private boolean load(VM vm, LValue chunkPartLoader, String chunkname) {
|
private boolean load(VM vm, LValue chunkPartLoader, String chunkname) {
|
||||||
if ( ! (chunkPartLoader instanceof Closure) ) {
|
if ( ! (chunkPartLoader instanceof Closure) ) {
|
||||||
vm.lua_error("not a closure: "+chunkPartLoader);
|
vm.error("not a closure: "+chunkPartLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
// load all the parts
|
// load all the parts
|
||||||
@@ -541,7 +541,7 @@ public class LuaCompat extends LFunction {
|
|||||||
try {
|
try {
|
||||||
while ( true ) {
|
while ( true ) {
|
||||||
vm.setResult(c);
|
vm.setResult(c);
|
||||||
if ( 0 != vm.lua_pcall(0, 1) ) {
|
if ( 0 != vm.pcall(0, 1, 0) ) {
|
||||||
vm.setErrorResult(LNil.NIL, vm.getArgAsString(0));
|
vm.setErrorResult(LNil.NIL, vm.getArgAsString(0));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -599,7 +599,7 @@ public class LuaCompat extends LFunction {
|
|||||||
// ======================== Module, Package loading =============================
|
// ======================== Module, Package loading =============================
|
||||||
|
|
||||||
public static void module( VM vm ) {
|
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 {
|
else {
|
||||||
String s = modname.toJavaString();
|
String s = modname.toJavaString();
|
||||||
if ( ! loadfile(vm, s+".luac") && ! loadfile(vm, s+".lua") )
|
if ( ! loadfile(vm, s+".luac") && ! loadfile(vm, s+".lua") )
|
||||||
vm.lua_error( "not found: "+s );
|
vm.error( "not found: "+s );
|
||||||
else if ( 0 == vm.lua_pcall(0, 1) ) {
|
else if ( 0 == vm.pcall(0, 1, 0) ) {
|
||||||
LValue result = vm.lua_tolvalue( -1 );
|
LValue result = vm.topointer( -1 );
|
||||||
if ( result != LNil.NIL )
|
if ( result != LNil.NIL )
|
||||||
LOADED.put(modname, result);
|
LOADED.put(modname, result);
|
||||||
else if ( ! LOADED.containsKey(modname) )
|
else if ( ! LOADED.containsKey(modname) )
|
||||||
@@ -648,11 +648,11 @@ public class LuaCompat extends LFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void loadlib( VM vm ) {
|
public static void loadlib( VM vm ) {
|
||||||
vm.lua_error( "loadlib not implemented" );
|
vm.error( "loadlib not implemented" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void seeall( VM vm ) {
|
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() ) );
|
vm.setResult( new LString( baos.toByteArray() ) );
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
vm.lua_error(e.getMessage());
|
vm.error(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public class StrLib {
|
|||||||
* TODO: port dumping code as optional add-on
|
* TODO: port dumping code as optional add-on
|
||||||
*/
|
*/
|
||||||
static void dump( VM vm ) {
|
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 ) );
|
lbuf.append( s.substring( soff, e ) );
|
||||||
} else {
|
} else {
|
||||||
push_onecapture( b - '1', soff, e );
|
push_onecapture( b - '1', soff, e );
|
||||||
lbuf.append( vm.lua_tolvalue( -1 ).luaAsString() );
|
lbuf.append( vm.topointer( -1 ).luaAsString() );
|
||||||
vm.lua_pop( 1 );
|
vm.pop( 1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -523,25 +523,25 @@ public class StrLib {
|
|||||||
} else if ( repl instanceof LFunction ) {
|
} else if ( repl instanceof LFunction ) {
|
||||||
vm.push( repl );
|
vm.push( repl );
|
||||||
int n = push_captures( true, soffset, end );
|
int n = push_captures( true, soffset, end );
|
||||||
vm.lua_call( n, 1 );
|
vm.call( n, 1 );
|
||||||
} else if ( repl instanceof LTable ) {
|
} else if ( repl instanceof LTable ) {
|
||||||
// Need to call push_onecapture here for the error checking
|
// Need to call push_onecapture here for the error checking
|
||||||
push_onecapture( 0, soffset, end );
|
push_onecapture( 0, soffset, end );
|
||||||
LValue k = vm.lua_tolvalue( -1 );
|
LValue k = vm.topointer( -1 );
|
||||||
vm.lua_pop( 1 );
|
vm.pop( 1 );
|
||||||
((LTable) repl).luaGetTable( vm, repl, k );
|
((LTable) repl).luaGetTable( vm, repl, k );
|
||||||
} else {
|
} else {
|
||||||
vm.lua_error( "string/function/table expected" );
|
vm.error( "string/function/table expected" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
repl = vm.lua_tolvalue( -1 );
|
repl = vm.topointer( -1 );
|
||||||
if ( !repl.luaAsBoolean() ) {
|
if ( !repl.luaAsBoolean() ) {
|
||||||
repl = s.substring( soffset, end );
|
repl = s.substring( soffset, end );
|
||||||
} else if ( ! ( repl instanceof LString || repl instanceof LNumber ) ) {
|
} 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() );
|
lbuf.append( repl.luaAsString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -558,12 +558,12 @@ public class StrLib {
|
|||||||
if ( i == 0 ) {
|
if ( i == 0 ) {
|
||||||
vm.push( s.substring( soff, end ) );
|
vm.push( s.substring( soff, end ) );
|
||||||
} else {
|
} else {
|
||||||
vm.lua_error( "invalid capture index" );
|
vm.error( "invalid capture index" );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int l = clen[i];
|
int l = clen[i];
|
||||||
if ( l == CAP_UNFINISHED ) {
|
if ( l == CAP_UNFINISHED ) {
|
||||||
vm.lua_error( "unfinished capture" );
|
vm.error( "unfinished capture" );
|
||||||
}
|
}
|
||||||
if ( l == CAP_POSITION ) {
|
if ( l == CAP_POSITION ) {
|
||||||
vm.push( LInteger.valueOf( cinit[i] + 1 ) );
|
vm.push( LInteger.valueOf( cinit[i] + 1 ) );
|
||||||
@@ -577,7 +577,7 @@ public class StrLib {
|
|||||||
private int check_capture( int l ) {
|
private int check_capture( int l ) {
|
||||||
l -= '1';
|
l -= '1';
|
||||||
if ( l < 0 || l >= level || this.clen[l] == CAP_UNFINISHED ) {
|
if ( l < 0 || l >= level || this.clen[l] == CAP_UNFINISHED ) {
|
||||||
vm.lua_error("invalid capture index");
|
vm.error("invalid capture index");
|
||||||
}
|
}
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
@@ -587,7 +587,7 @@ public class StrLib {
|
|||||||
for ( level--; level >= 0; level-- )
|
for ( level--; level >= 0; level-- )
|
||||||
if ( clen[level] == CAP_UNFINISHED )
|
if ( clen[level] == CAP_UNFINISHED )
|
||||||
return level;
|
return level;
|
||||||
vm.lua_error("invalid pattern capture");
|
vm.error("invalid pattern capture");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -595,7 +595,7 @@ public class StrLib {
|
|||||||
switch ( p.luaByte( poffset++ ) ) {
|
switch ( p.luaByte( poffset++ ) ) {
|
||||||
case L_ESC:
|
case L_ESC:
|
||||||
if ( poffset == p.length() ) {
|
if ( poffset == p.length() ) {
|
||||||
vm.lua_error( "malformed pattern (ends with %)" );
|
vm.error( "malformed pattern (ends with %)" );
|
||||||
}
|
}
|
||||||
return poffset + 1;
|
return poffset + 1;
|
||||||
|
|
||||||
@@ -603,7 +603,7 @@ public class StrLib {
|
|||||||
if ( p.luaByte( poffset ) == '^' ) poffset++;
|
if ( p.luaByte( poffset ) == '^' ) poffset++;
|
||||||
do {
|
do {
|
||||||
if ( poffset == p.length() ) {
|
if ( poffset == p.length() ) {
|
||||||
vm.lua_error( "malformed pattern (missing ])" );
|
vm.error( "malformed pattern (missing ])" );
|
||||||
}
|
}
|
||||||
if ( p.luaByte( poffset++ ) == L_ESC && poffset != p.length() )
|
if ( p.luaByte( poffset++ ) == L_ESC && poffset != p.length() )
|
||||||
poffset++;
|
poffset++;
|
||||||
@@ -695,7 +695,7 @@ public class StrLib {
|
|||||||
case 'f': {
|
case 'f': {
|
||||||
poffset += 2;
|
poffset += 2;
|
||||||
if ( p.luaByte( poffset ) != '[' ) {
|
if ( p.luaByte( poffset ) != '[' ) {
|
||||||
vm.lua_error("Missing [ after %f in pattern");
|
vm.error("Missing [ after %f in pattern");
|
||||||
}
|
}
|
||||||
int ep = classend( poffset );
|
int ep = classend( poffset );
|
||||||
int previous = ( soffset == 0 ) ? -1 : s.luaByte( soffset - 1 );
|
int previous = ( soffset == 0 ) ? -1 : s.luaByte( soffset - 1 );
|
||||||
@@ -775,7 +775,7 @@ public class StrLib {
|
|||||||
int res;
|
int res;
|
||||||
int level = this.level;
|
int level = this.level;
|
||||||
if ( level >= MAX_CAPTURES ) {
|
if ( level >= MAX_CAPTURES ) {
|
||||||
vm.lua_error( "too many captures" );
|
vm.error( "too many captures" );
|
||||||
}
|
}
|
||||||
cinit[ level ] = soff;
|
cinit[ level ] = soff;
|
||||||
clen[ level ] = what;
|
clen[ level ] = what;
|
||||||
@@ -807,7 +807,7 @@ public class StrLib {
|
|||||||
int matchbalance( int soff, int poff ) {
|
int matchbalance( int soff, int poff ) {
|
||||||
final int plen = p.length();
|
final int plen = p.length();
|
||||||
if ( poff == plen || poff + 1 == plen ) {
|
if ( poff == plen || poff + 1 == plen ) {
|
||||||
vm.lua_error( "unbalanced pattern" );
|
vm.error( "unbalanced pattern" );
|
||||||
}
|
}
|
||||||
if ( s.luaByte( soff ) != p.luaByte( poff ) )
|
if ( s.luaByte( soff ) != p.luaByte( poff ) )
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -78,9 +78,9 @@ final class Builtin extends LFunction {
|
|||||||
break;
|
break;
|
||||||
case PCALL: {
|
case PCALL: {
|
||||||
int n = vm.getArgCount();
|
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 ) {
|
if ( s != 0 ) {
|
||||||
LValue v = vm.lua_tolvalue(-1);
|
LValue v = vm.topointer(-1);
|
||||||
vm.setResult( LBoolean.FALSE );
|
vm.setResult( LBoolean.FALSE );
|
||||||
vm.push( v );
|
vm.push( v );
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
74
src/main/java/lua/JavaFunction.java
Normal file
74
src/main/java/lua/JavaFunction.java
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
package lua;
|
||||||
|
|
||||||
|
import lua.value.LFunction;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Type for Java functions.
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In order to communicate properly with Lua,
|
||||||
|
a Java function must use the following protocol,
|
||||||
|
which defines the way parameters and results are passed:
|
||||||
|
a Java 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 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 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 <= 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
@@ -89,8 +89,8 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|||||||
|
|
||||||
|
|
||||||
// override and fill in line number info
|
// override and fill in line number info
|
||||||
public void lua_error(String message) {
|
public void error(String message) {
|
||||||
super.lua_error( getFileLine(cc)+": "+message );
|
super.error( getFileLine(cc)+": "+message );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printLuaTrace() {
|
private void printLuaTrace() {
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ public class LFunction extends LValue {
|
|||||||
vm.push( table );
|
vm.push( table );
|
||||||
vm.push( key );
|
vm.push( key );
|
||||||
vm.push( val );
|
vm.push( val );
|
||||||
vm.lua_call( 3, 0 );
|
vm.call( 3, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void luaGetTable(VM vm, LValue table, LValue key) {
|
public void luaGetTable(VM vm, LValue table, LValue key) {
|
||||||
vm.push( this );
|
vm.push( this );
|
||||||
vm.push( table );
|
vm.push( table );
|
||||||
vm.push( key );
|
vm.push( key );
|
||||||
vm.lua_call( 2, 1 );
|
vm.call( 2, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
public int luaGetType() {
|
public int luaGetType() {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class LValue {
|
|||||||
// perform a lua call, return true if the call is to a lua function, false
|
// perform a lua call, return true if the call is to a lua function, false
|
||||||
// if it ran to completion.
|
// if it ran to completion.
|
||||||
public boolean luaStackCall(VM vm) {
|
public boolean luaStackCall(VM vm) {
|
||||||
vm.lua_error("attempt to call "+this);
|
vm.error("attempt to call "+this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user