From f8b7e1ee1cbaea677c22eee6034bb1743e9fb0be Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Mon, 10 Sep 2012 04:59:45 +0000 Subject: [PATCH] Refactor table library to match lua 5.2 --- src/core/org/luaj/vm2/LuaDouble.java | 6 +- src/core/org/luaj/vm2/LuaNil.java | 4 +- src/core/org/luaj/vm2/LuaTable.java | 3 +- src/core/org/luaj/vm2/LuaValue.java | 7 +- src/core/org/luaj/vm2/lib/LibFunction.java | 26 ++++ src/core/org/luaj/vm2/lib/TableLib.java | 137 ++++++++++++--------- src/jse/lua.java | 2 + test/lua/errors/args.lua | 2 +- test/lua/tablelib.lua | 12 +- 9 files changed, 125 insertions(+), 74 deletions(-) diff --git a/src/core/org/luaj/vm2/LuaDouble.java b/src/core/org/luaj/vm2/LuaDouble.java index 85b151ce..5061d732 100644 --- a/src/core/org/luaj/vm2/LuaDouble.java +++ b/src/core/org/luaj/vm2/LuaDouble.java @@ -280,9 +280,7 @@ public class LuaDouble extends LuaNumber { return LuaString.valueOf(tojstring()); } - public LuaValue checkvalidkey() { - if ( Double.isNaN(v) ) - throw new LuaError("table index expected, got nan"); - return this; + public boolean isvalidkey() { + return !Double.isNaN(v); } } diff --git a/src/core/org/luaj/vm2/LuaNil.java b/src/core/org/luaj/vm2/LuaNil.java index b5f264bf..1b247cbd 100644 --- a/src/core/org/luaj/vm2/LuaNil.java +++ b/src/core/org/luaj/vm2/LuaNil.java @@ -85,8 +85,8 @@ public class LuaNil extends LuaValue { return argerror("value"); } - public LuaValue checkvalidkey() { - return typerror("table index"); + public boolean isvalidkey() { + return false; } // optional argument conversions - nil alwas falls badk to default value diff --git a/src/core/org/luaj/vm2/LuaTable.java b/src/core/org/luaj/vm2/LuaTable.java index 53f79cab..6a7793fd 100644 --- a/src/core/org/luaj/vm2/LuaTable.java +++ b/src/core/org/luaj/vm2/LuaTable.java @@ -272,7 +272,8 @@ public class LuaTable extends LuaValue { /** caller must ensure key is not nil */ 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) ) rawset(key, value); } diff --git a/src/core/org/luaj/vm2/LuaValue.java b/src/core/org/luaj/vm2/LuaValue.java index 4e628f5e..8b6d433d 100644 --- a/src/core/org/luaj/vm2/LuaValue.java +++ b/src/core/org/luaj/vm2/LuaValue.java @@ -1027,13 +1027,12 @@ public class LuaValue extends Varargs { */ public LuaValue checknotnil() { return this; } - /** Check that this is a valid key in a table index operation, or throw {@link LuaError} if not - * @return {@code this} if valid as a table key - * @throws LuaError if not valid as a table key + /** Return true if this is a valid key in a table index operation. + * @return true if valid as a table key, otherwise false * @see #isnil() * @see #isinttype() */ - public LuaValue checkvalidkey() { return this; } + public boolean isvalidkey() { return true; } /** * Throw a {@link LuaError} with a particular message diff --git a/src/core/org/luaj/vm2/lib/LibFunction.java b/src/core/org/luaj/vm2/lib/LibFunction.java index 0d72ab17..fb84018e 100644 --- a/src/core/org/luaj/vm2/lib/LibFunction.java +++ b/src/core/org/luaj/vm2/lib/LibFunction.java @@ -24,6 +24,7 @@ package org.luaj.vm2.lib; import org.luaj.vm2.LuaError; import org.luaj.vm2.LuaFunction; import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; /** * 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) { 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)); + } + } } diff --git a/src/core/org/luaj/vm2/lib/TableLib.java b/src/core/org/luaj/vm2/lib/TableLib.java index 4fd5f518..a68090f2 100644 --- a/src/core/org/luaj/vm2/lib/TableLib.java +++ b/src/core/org/luaj/vm2/lib/TableLib.java @@ -58,66 +58,91 @@ import org.luaj.vm2.Varargs; */ public class TableLib extends OneArgFunction { - public TableLib() { - } - - private LuaTable init(LuaValue env) { - LuaTable t = new LuaTable(); - bind(t, TableLib.class, new String[] {}, 1 ); - bind(t, TableLibV.class, new String[] { - "remove", "concat", "insert", "sort", "unpack", } ); - env.set("table", t); - PackageLib.instance.LOADED.set("table", t); - return t; - } - - public LuaValue call(LuaValue arg) { - switch ( opcode ) { - case 0: // init library - return init(arg); - } + public LuaValue call(LuaValue env) { + LuaTable table = new LuaTable(); + table.set("concat", new concat()); + table.set("insert", new insert()); + table.set("pack", new pack()); + table.set("remove", new remove()); + table.set("sort", new sort()); + table.set("unpack", new unpack()); + env.set("table", table); return NIL; } - static final class TableLibV extends VarArgFunction { - public Varargs invoke(Varargs args) { - switch ( opcode ) { - 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); - } - case 1: { // "concat" (table [, sep [, i [, j]]]) -> string - LuaTable table = args.checktable(1); - return table.concat( - args.optstring(2,LuaValue.EMPTYSTRING), - args.optint(3,1), - args.isvalue(4)? args.checkint(4): table.length() ); - } - case 2: { // "insert" (table, [pos,] value) -> prev-ele - final LuaTable table = args.checktable(1); - final int pos = args.narg()>2? args.checkint(2): 0; - final LuaValue value = args.arg( args.narg()>2? 3: 2 ); - table.insert( pos, value ); - return NONE; - } - case 3: { // "sort" (table [, comp]) -> void - LuaTable table = args.checktable(1); - LuaValue compare = (args.isnoneornil(2)? NIL: args.checkfunction(2)); - table.sort( compare ); - return NONE; - } - case 4: // "unpack", // (list [,i [,j]]) -> result1, ... - { - 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)); - } - } - } + static class TableLibFunction extends LibFunction { + public LuaValue call() { + return argerror(1, "table expected, got no value"); + } + } + + // "concat" (table [, sep [, i [, j]]]) -> string + static class concat extends TableLibFunction { + public LuaValue call(LuaValue list) { + return list.checktable().concat(EMPTYSTRING,1,list.length()); + } + public LuaValue call(LuaValue list, LuaValue sep) { + return list.checktable().concat(sep.checkstring(),1,list.length()); + } + public LuaValue call(LuaValue list, LuaValue sep, LuaValue i) { + return list.checktable().concat(sep.checkstring(),i.checkint(),list.length()); + } + public LuaValue call(LuaValue list, LuaValue sep, LuaValue i, LuaValue j) { + return list.checktable().concat(sep.checkstring(),i.checkint(),j.checkint()); + } + } + + // "insert" (table, [pos,] value) -> prev-ele + static class insert extends TableLibFunction { + public LuaValue call(LuaValue list) { + return argerror(2, "value expected"); + } + public LuaValue call(LuaValue table, LuaValue value) { + table.checktable().insert(table.length()+1,value); + return NONE; + } + public LuaValue call(LuaValue table, LuaValue pos, LuaValue value) { + table.checktable().insert(pos.checkint(),value); 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)); + } + } + } } diff --git a/src/jse/lua.java b/src/jse/lua.java index a8c9b3b9..b1ebdf45 100644 --- a/src/jse/lua.java +++ b/src/jse/lua.java @@ -198,6 +198,8 @@ public class lua { } private static Varargs setGlobalArg(String chunkname, String[] args, int i, LuaValue _G) { + if (args == null) + return LuaValue.NONE; LuaTable arg = LuaValue.tableOf(); for ( int j=0; j