Refactor table library to match lua 5.2

This commit is contained in:
James Roseborough
2012-09-10 04:59:45 +00:00
parent 6ba1f86b7b
commit f8b7e1ee1c
9 changed files with 125 additions and 74 deletions

View File

@@ -280,9 +280,7 @@ public class LuaDouble extends LuaNumber {
return LuaString.valueOf(tojstring()); return LuaString.valueOf(tojstring());
} }
public LuaValue checkvalidkey() { public boolean isvalidkey() {
if ( Double.isNaN(v) ) return !Double.isNaN(v);
throw new LuaError("table index expected, got nan");
return this;
} }
} }

View File

@@ -85,8 +85,8 @@ public class LuaNil extends LuaValue {
return argerror("value"); return argerror("value");
} }
public LuaValue checkvalidkey() { public boolean isvalidkey() {
return typerror("table index"); return false;
} }
// optional argument conversions - nil alwas falls badk to default value // optional argument conversions - nil alwas falls badk to default value

View File

@@ -272,7 +272,8 @@ public class LuaTable extends LuaValue {
/** caller must ensure key is not nil */ /** caller must ensure key is not nil */
public void set( LuaValue key, LuaValue value ) { public void set( LuaValue key, LuaValue value ) {
key.checkvalidkey(); if (!key.isvalidkey() && !metatag(NEWINDEX).isfunction())
typerror("table index");
if ( m_metatable==null || ! rawget(key).isnil() || ! settable(this,key,value) ) if ( m_metatable==null || ! rawget(key).isnil() || ! settable(this,key,value) )
rawset(key, value); rawset(key, value);
} }

View File

@@ -1027,13 +1027,12 @@ public class LuaValue extends Varargs {
*/ */
public LuaValue checknotnil() { return this; } public LuaValue checknotnil() { return this; }
/** Check that this is a valid key in a table index operation, or throw {@link LuaError} if not /** Return true if this is a valid key in a table index operation.
* @return {@code this} if valid as a table key * @return true if valid as a table key, otherwise false
* @throws LuaError if not valid as a table key
* @see #isnil() * @see #isnil()
* @see #isinttype() * @see #isinttype()
*/ */
public LuaValue checkvalidkey() { return this; } public boolean isvalidkey() { return true; }
/** /**
* Throw a {@link LuaError} with a particular message * Throw a {@link LuaError} with a particular message

View File

@@ -24,6 +24,7 @@ package org.luaj.vm2.lib;
import org.luaj.vm2.LuaError; import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaFunction; import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaValue; import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
/** /**
* Subclass of {@link LuaFunction} common to Java functions exposed to lua. * Subclass of {@link LuaFunction} common to Java functions exposed to lua.
@@ -190,4 +191,29 @@ abstract public class LibFunction extends LuaFunction {
protected static LuaValue[] newupl(LuaValue v) { protected static LuaValue[] newupl(LuaValue v) {
return new LuaValue[] { v }; return new LuaValue[] { v };
} }
public LuaValue call() {
return typerror("value");
}
public LuaValue call(LuaValue a) {
return call();
}
public LuaValue call(LuaValue a, LuaValue b) {
return call(a);
}
public LuaValue call(LuaValue a, LuaValue b, LuaValue c) {
return call(a,b);
}
public LuaValue call(LuaValue a, LuaValue b, LuaValue c, LuaValue d) {
return call(a,b,c);
}
public Varargs invoke(Varargs args) {
switch(args.narg()) {
case 0: return call();
case 1: return call(args.arg1());
case 2: return call(args.arg1(),args.arg(2));
case 3: return call(args.arg1(),args.arg(2),args.arg(3));
default: return call(args.arg1(),args.arg(2),args.arg(3),args.arg(4));
}
}
} }

View File

@@ -58,66 +58,91 @@ import org.luaj.vm2.Varargs;
*/ */
public class TableLib extends OneArgFunction { public class TableLib extends OneArgFunction {
public TableLib() { public LuaValue call(LuaValue env) {
} LuaTable table = new LuaTable();
table.set("concat", new concat());
private LuaTable init(LuaValue env) { table.set("insert", new insert());
LuaTable t = new LuaTable(); table.set("pack", new pack());
bind(t, TableLib.class, new String[] {}, 1 ); table.set("remove", new remove());
bind(t, TableLibV.class, new String[] { table.set("sort", new sort());
"remove", "concat", "insert", "sort", "unpack", } ); table.set("unpack", new unpack());
env.set("table", t); env.set("table", table);
PackageLib.instance.LOADED.set("table", t);
return t;
}
public LuaValue call(LuaValue arg) {
switch ( opcode ) {
case 0: // init library
return init(arg);
}
return NIL; return NIL;
} }
static final class TableLibV extends VarArgFunction { static class TableLibFunction extends LibFunction {
public Varargs invoke(Varargs args) { public LuaValue call() {
switch ( opcode ) { return argerror(1, "table expected, got no value");
case 0: { // "remove" (table [, pos]) -> removed-ele }
LuaTable table = args.checktable(1); }
int pos = args.narg()>1? args.checkint(2): 0;
return table.remove(pos); // "concat" (table [, sep [, i [, j]]]) -> string
} static class concat extends TableLibFunction {
case 1: { // "concat" (table [, sep [, i [, j]]]) -> string public LuaValue call(LuaValue list) {
LuaTable table = args.checktable(1); return list.checktable().concat(EMPTYSTRING,1,list.length());
return table.concat( }
args.optstring(2,LuaValue.EMPTYSTRING), public LuaValue call(LuaValue list, LuaValue sep) {
args.optint(3,1), return list.checktable().concat(sep.checkstring(),1,list.length());
args.isvalue(4)? args.checkint(4): table.length() ); }
} public LuaValue call(LuaValue list, LuaValue sep, LuaValue i) {
case 2: { // "insert" (table, [pos,] value) -> prev-ele return list.checktable().concat(sep.checkstring(),i.checkint(),list.length());
final LuaTable table = args.checktable(1); }
final int pos = args.narg()>2? args.checkint(2): 0; public LuaValue call(LuaValue list, LuaValue sep, LuaValue i, LuaValue j) {
final LuaValue value = args.arg( args.narg()>2? 3: 2 ); return list.checktable().concat(sep.checkstring(),i.checkint(),j.checkint());
table.insert( pos, value ); }
return NONE; }
}
case 3: { // "sort" (table [, comp]) -> void // "insert" (table, [pos,] value) -> prev-ele
LuaTable table = args.checktable(1); static class insert extends TableLibFunction {
LuaValue compare = (args.isnoneornil(2)? NIL: args.checkfunction(2)); public LuaValue call(LuaValue list) {
table.sort( compare ); return argerror(2, "value expected");
return NONE; }
} public LuaValue call(LuaValue table, LuaValue value) {
case 4: // "unpack", // (list [,i [,j]]) -> result1, ... table.checktable().insert(table.length()+1,value);
{ return NONE;
LuaTable t = args.checktable(1); }
switch (args.narg()) { public LuaValue call(LuaValue table, LuaValue pos, LuaValue value) {
case 1: return t.unpack(); table.checktable().insert(pos.checkint(),value);
case 2: return t.unpack(args.checkint(2));
default: return t.unpack(args.checkint(2), args.checkint(3));
}
}
}
return NONE; return NONE;
} }
} }
// "pack" (...) -> table
static class pack extends VarArgFunction {
public Varargs invoke(Varargs args) {
LuaValue t = tableOf(args, 1);
t.set("n", args.narg());
return t;
}
}
// "remove" (table [, pos]) -> removed-ele
static class remove extends TableLibFunction {
public LuaValue call(LuaValue list) {
return list.checktable().remove(0);
}
public LuaValue call(LuaValue list, LuaValue pos) {
return list.checktable().remove(pos.checkint());
}
}
// "sort" (table [, comp])
static class sort extends TwoArgFunction {
public LuaValue call(LuaValue table, LuaValue compare) {
table.checktable().sort(compare.isnil()? NIL: compare.checkfunction());
return NONE;
}
}
// "unpack", // (list [,i [,j]]) -> result1, ...
static class unpack extends VarArgFunction {
public Varargs invoke(Varargs args) {
LuaTable t = args.checktable(1);
switch (args.narg()) {
case 1: return t.unpack();
case 2: return t.unpack(args.checkint(2));
default: return t.unpack(args.checkint(2), args.checkint(3));
}
}
}
} }

View File

@@ -198,6 +198,8 @@ public class lua {
} }
private static Varargs setGlobalArg(String chunkname, String[] args, int i, LuaValue _G) { private static Varargs setGlobalArg(String chunkname, String[] args, int i, LuaValue _G) {
if (args == null)
return LuaValue.NONE;
LuaTable arg = LuaValue.tableOf(); LuaTable arg = LuaValue.tableOf();
for ( int j=0; j<args.length; j++ ) for ( int j=0; j<args.length; j++ )
arg.set( j-i, LuaValue.valueOf(args[j]) ); arg.set( j-i, LuaValue.valueOf(args[j]) );

View File

@@ -114,7 +114,7 @@ local function split(t)
end end
local function expand(argsets, typesets, ...) local function expand(argsets, typesets, ...)
local arg = {...} ; arg.n = #arg local arg = table.pack(...)
local n = typesets and #typesets or 0 local n = typesets and #typesets or 0
if n <= 0 then if n <= 0 then
table.insert(argsets,arg) table.insert(argsets,arg)

View File

@@ -133,10 +133,10 @@ testbothpairs(t)
-- length is tested elsewhere -- length is tested elsewhere
print('----- unpack tests -------') print('----- unpack tests -------')
local unpack = table.unpack local unpack = table.unpack
print( 'pcall(unpack)', pcall(unpack) ); print( 'pcall(unpack)', (pcall(unpack)) );
print( 'pcall(unpack,nil)', pcall(unpack,nil) ); print( 'pcall(unpack,nil)', (pcall(unpack,nil)) );
print( 'pcall(unpack,"abc")', pcall(unpack,"abc") ); print( 'pcall(unpack,"abc")', (pcall(unpack,"abc")) );
print( 'pcall(unpack,1)', pcall(unpack,1) ); print( 'pcall(unpack,1)', (pcall(unpack,1)) );
print( 'unpack({"aa"})', unpack({"aa"}) ); print( 'unpack({"aa"})', unpack({"aa"}) );
print( 'unpack({"aa","bb"})', unpack({"aa","bb"}) ); print( 'unpack({"aa","bb"})', unpack({"aa","bb"}) );
print( 'unpack({"aa","bb","cc"})', unpack({"aa","bb","cc"}) ); print( 'unpack({"aa","bb","cc"})', unpack({"aa","bb","cc"}) );
@@ -203,8 +203,8 @@ print( 'pcall(unpack,t,0)', pcall(unpack,t,0) );
print( 'pcall(unpack,t,2,0)', pcall(unpack,t,2,0) ); print( 'pcall(unpack,t,2,0)', pcall(unpack,t,2,0) );
print( 'pcall(unpack,t,2,-1)', pcall(unpack,t,2,-1) ); print( 'pcall(unpack,t,2,-1)', pcall(unpack,t,2,-1) );
print( 'pcall(unpack,t,"3")', pcall(unpack,t,"3") ); print( 'pcall(unpack,t,"3")', pcall(unpack,t,"3") );
print( 'pcall(unpack,t,"a")', pcall(unpack,t,"a") ); print( 'pcall(unpack,t,"a")', (pcall(unpack,t,"a")) );
print( 'pcall(unpack,t,function() end)', pcall(unpack,t,function() end) ); print( 'pcall(unpack,t,function() end)', (pcall(unpack,t,function() end)) );
-- misc tests -- misc tests
print('----- misc table initializer tests -------') print('----- misc table initializer tests -------')