fix setmetatable() to match C version

This commit is contained in:
James Roseborough
2007-12-07 00:52:39 +00:00
parent dc08fcbec2
commit d7c15f99a1
9 changed files with 51 additions and 35 deletions

View File

@@ -118,7 +118,8 @@ public class BaseLib extends LFunction {
Lua.TYPE_NAMES[type]+" expected, got no value)") );
}
private void checkargtype(LuaState vm, int index, int type) {
private void checkargtype
(LuaState vm, int index, int type) {
checkargexists( vm, index, type );
int t = vm.type(index);
if ( t != type ) {
@@ -164,8 +165,11 @@ public class BaseLib extends LFunction {
}
case SETMETATABLE: {
checkargtype(vm,2,Lua.LUA_TTABLE);
if ( vm.gettop()<3 || ! (vm.isnil(3) || vm.istable(3)) )
vm.error( "bad argument #2 to '?' (nil or table expected)" );
vm.setmetatable(2);
vm.remove(1);
vm.settop(1);
break;
}
case TYPE: {

View File

@@ -43,7 +43,7 @@ public class PackageLib extends LFunction {
public static InputStream STDIN = null;
public static PrintStream STDOUT = System.out;
public static LTable LOADED = new LTable();
public static LTable LOADED = null;
private static final LString _M = new LString("_M");
private static final LString _NAME = new LString("_NAME");
@@ -86,6 +86,7 @@ public class PackageLib extends LFunction {
pckg = new LTable();
for ( int i=LOADLIB; i<=SEEALL; i++ )
pckg.put( NAMES[i], new PackageLib(i) );
LOADED = new LTable();
pckg.put( "loaded", LOADED );
pckg.put( _PRELOAD, new LTable() );
LTable loaders = new LTable(3,0);

View File

@@ -85,8 +85,6 @@ public class LTable extends LValue {
private LTable m_metatable;
/** Construct an empty LTable with no initial capacity. */
public LTable() {
m_vector = EMPTY_ARRAY;
@@ -273,8 +271,14 @@ public class LTable extends LValue {
/** Valid for tables */
public void luaSetMetatable(LValue metatable) {
this.m_metatable = ( metatable != null && metatable != LNil.NIL ) ?
(LTable) metatable : null;
if ( m_metatable != null && m_metatable.containsKey(TM_METATABLE) )
throw new LuaErrorException("cannot change a protected metatable");
if ( metatable == null || metatable == LNil.NIL )
this.m_metatable = null;
else if ( metatable.luaGetType() == Lua.LUA_TTABLE )
this.m_metatable = (LTable) metatable;
else
throw new LuaErrorException("nil or table expected, got "+metatable.luaGetTypeName());
}
public String toJavaString() {

View File

@@ -31,6 +31,9 @@ public class LValue {
/** Metatable tag for intercepting table sets */
public static final LString TM_NEWINDEX = new LString("__newindex");
/** Metatable tag for intercepting table sets */
public static final LString TM_METATABLE = new LString("__metatable");
protected void conversionError(String target) {
throw new LuaErrorException( "bad conversion: "+luaGetTypeName()+" to "+target );
}
@@ -70,12 +73,12 @@ public class LValue {
// unsupported except for numbers
public LValue luaBinOpInteger(int opcode, int m_value) {
return arithmeticError("number");
return arithmeticError(luaGetTypeName());
}
// unsupported except for numbers
public LValue luaBinOpDouble(int opcode, double m_value) {
return arithmeticError("number");
return arithmeticError(luaGetTypeName());
}
// unsupported except for numbers, strings, and == with various combinations of Nil, Boolean, etc.

View File

@@ -141,7 +141,7 @@ public class LuaJTest extends TestCase {
private void runTest( String testName ) throws IOException, InterruptedException {
// new lua state
LuaState state = new DebugLuaState();
LuaState state = LuaState.newState();
// add standard bindings
state.installStandardLibs();

View File

@@ -1,14 +1,6 @@
-- unit tests for functions in BaseLib.java
local ids = {}
local function id(obj)
local v = ids[obj]
if v then
return v
end
table.insert(ids,obj)
ids[obj] = type(obj)..'.'..tostring(#ids)
return ids[obj]
end
package.path = "?.lua;src/test/res/?.lua"
require 'ids'
-- print
print()

View File

@@ -1,7 +1,6 @@
-- object ids
package.path = "?.lua;src/test/res/?.lua"
require 'ids'
ids = {}
-- test of common types of errors
local function c(f,...) return f(...) end
@@ -9,7 +8,6 @@ local function b(...) return c(...) end
local function a(...) return pcall(b,...) end
s = 'some string'
local t = {}
-- error message tests
print( 'a(error)', a(error) )
print( 'a(error,"msg")', a(error,"msg") )

View File

@@ -1,5 +1,31 @@
package.path = "?.lua;src/test/res/?.lua"
require 'ids'
-- The purpose of this test case is to demonstrate that
-- basic metatable operations on non-table types work.
-- i.e. that s.sub(s,...) could be used in place of string.sub(s,...)
local s = "hello"
print(s:sub(2,4))
local t = {}
function op(name,...)
a,b,c,d = pcall( setmetatable, t, ... )
print( name, id(t), id(getmetatable(t)), id(a), id(b), id(c), id(d) )
end
op('set{} ',{})
op('set-nil',nil)
op('set{} ',{})
op('set')
op('set{} ',{})
op('set{} ',{})
op('set{}{}',{},{})
op('set-nil',nil)
op('set{__}',{__metatable={}})
op('set{} ',{})
op('set-nil',nil)
t = {}
op('set{} ',{})
op('set-nil',nil)
op('set{__}',{__metatable='abc'})
op('set{} ',{})
op('set-nil',nil)

View File

@@ -1,18 +1,6 @@
-- unit tests for require() function
local ids = {}
local ti = table.insert
local function id(obj)
if not obj or type(obj) == 'number' or type(obj) == 'string' or type(obj) == 'boolean' then
return obj
end
local v = ids[obj]
if v then
return v
end
ti(ids,obj)
ids[obj] = type(obj)..'.'..tostring(#ids)
return ids[obj]
end
package.path = "?.lua;src/test/res/?.lua"
require 'ids'
-- tests on require
package.path='?.lua;src/test/res/?.lua'