fix setmetatable() to match C version
This commit is contained in:
@@ -118,7 +118,8 @@ public class BaseLib extends LFunction {
|
|||||||
Lua.TYPE_NAMES[type]+" expected, got no value)") );
|
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 );
|
checkargexists( vm, index, type );
|
||||||
int t = vm.type(index);
|
int t = vm.type(index);
|
||||||
if ( t != type ) {
|
if ( t != type ) {
|
||||||
@@ -164,8 +165,11 @@ public class BaseLib extends LFunction {
|
|||||||
}
|
}
|
||||||
case SETMETATABLE: {
|
case SETMETATABLE: {
|
||||||
checkargtype(vm,2,Lua.LUA_TTABLE);
|
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.setmetatable(2);
|
||||||
vm.remove(1);
|
vm.remove(1);
|
||||||
|
vm.settop(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TYPE: {
|
case TYPE: {
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class PackageLib extends LFunction {
|
|||||||
|
|
||||||
public static InputStream STDIN = null;
|
public static InputStream STDIN = null;
|
||||||
public static PrintStream STDOUT = System.out;
|
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 _M = new LString("_M");
|
||||||
private static final LString _NAME = new LString("_NAME");
|
private static final LString _NAME = new LString("_NAME");
|
||||||
@@ -86,6 +86,7 @@ public class PackageLib extends LFunction {
|
|||||||
pckg = new LTable();
|
pckg = new LTable();
|
||||||
for ( int i=LOADLIB; i<=SEEALL; i++ )
|
for ( int i=LOADLIB; i<=SEEALL; i++ )
|
||||||
pckg.put( NAMES[i], new PackageLib(i) );
|
pckg.put( NAMES[i], new PackageLib(i) );
|
||||||
|
LOADED = new LTable();
|
||||||
pckg.put( "loaded", LOADED );
|
pckg.put( "loaded", LOADED );
|
||||||
pckg.put( _PRELOAD, new LTable() );
|
pckg.put( _PRELOAD, new LTable() );
|
||||||
LTable loaders = new LTable(3,0);
|
LTable loaders = new LTable(3,0);
|
||||||
|
|||||||
@@ -85,8 +85,6 @@ public class LTable extends LValue {
|
|||||||
|
|
||||||
private LTable m_metatable;
|
private LTable m_metatable;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Construct an empty LTable with no initial capacity. */
|
/** Construct an empty LTable with no initial capacity. */
|
||||||
public LTable() {
|
public LTable() {
|
||||||
m_vector = EMPTY_ARRAY;
|
m_vector = EMPTY_ARRAY;
|
||||||
@@ -273,8 +271,14 @@ public class LTable extends LValue {
|
|||||||
|
|
||||||
/** Valid for tables */
|
/** Valid for tables */
|
||||||
public void luaSetMetatable(LValue metatable) {
|
public void luaSetMetatable(LValue metatable) {
|
||||||
this.m_metatable = ( metatable != null && metatable != LNil.NIL ) ?
|
if ( m_metatable != null && m_metatable.containsKey(TM_METATABLE) )
|
||||||
(LTable) metatable : null;
|
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() {
|
public String toJavaString() {
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ public class LValue {
|
|||||||
/** Metatable tag for intercepting table sets */
|
/** Metatable tag for intercepting table sets */
|
||||||
public static final LString TM_NEWINDEX = new LString("__newindex");
|
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) {
|
protected void conversionError(String target) {
|
||||||
throw new LuaErrorException( "bad conversion: "+luaGetTypeName()+" to "+target );
|
throw new LuaErrorException( "bad conversion: "+luaGetTypeName()+" to "+target );
|
||||||
}
|
}
|
||||||
@@ -70,12 +73,12 @@ public class LValue {
|
|||||||
|
|
||||||
// unsupported except for numbers
|
// unsupported except for numbers
|
||||||
public LValue luaBinOpInteger(int opcode, int m_value) {
|
public LValue luaBinOpInteger(int opcode, int m_value) {
|
||||||
return arithmeticError("number");
|
return arithmeticError(luaGetTypeName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsupported except for numbers
|
// unsupported except for numbers
|
||||||
public LValue luaBinOpDouble(int opcode, double m_value) {
|
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.
|
// unsupported except for numbers, strings, and == with various combinations of Nil, Boolean, etc.
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ public class LuaJTest extends TestCase {
|
|||||||
private void runTest( String testName ) throws IOException, InterruptedException {
|
private void runTest( String testName ) throws IOException, InterruptedException {
|
||||||
|
|
||||||
// new lua state
|
// new lua state
|
||||||
LuaState state = new DebugLuaState();
|
LuaState state = LuaState.newState();
|
||||||
|
|
||||||
// add standard bindings
|
// add standard bindings
|
||||||
state.installStandardLibs();
|
state.installStandardLibs();
|
||||||
|
|||||||
@@ -1,14 +1,6 @@
|
|||||||
-- unit tests for functions in BaseLib.java
|
-- unit tests for functions in BaseLib.java
|
||||||
local ids = {}
|
package.path = "?.lua;src/test/res/?.lua"
|
||||||
local function id(obj)
|
require 'ids'
|
||||||
local v = ids[obj]
|
|
||||||
if v then
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
table.insert(ids,obj)
|
|
||||||
ids[obj] = type(obj)..'.'..tostring(#ids)
|
|
||||||
return ids[obj]
|
|
||||||
end
|
|
||||||
|
|
||||||
-- print
|
-- print
|
||||||
print()
|
print()
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
-- object ids
|
-- object ids
|
||||||
package.path = "?.lua;src/test/res/?.lua"
|
package.path = "?.lua;src/test/res/?.lua"
|
||||||
require 'ids'
|
require 'ids'
|
||||||
ids = {}
|
|
||||||
|
|
||||||
-- test of common types of errors
|
-- test of common types of errors
|
||||||
local function c(f,...) return f(...) end
|
local function c(f,...) return f(...) end
|
||||||
@@ -9,7 +8,6 @@ local function b(...) return c(...) end
|
|||||||
local function a(...) return pcall(b,...) end
|
local function a(...) return pcall(b,...) end
|
||||||
s = 'some string'
|
s = 'some string'
|
||||||
local t = {}
|
local t = {}
|
||||||
|
|
||||||
-- error message tests
|
-- error message tests
|
||||||
print( 'a(error)', a(error) )
|
print( 'a(error)', a(error) )
|
||||||
print( 'a(error,"msg")', a(error,"msg") )
|
print( 'a(error,"msg")', a(error,"msg") )
|
||||||
|
|||||||
@@ -1,5 +1,31 @@
|
|||||||
|
package.path = "?.lua;src/test/res/?.lua"
|
||||||
|
require 'ids'
|
||||||
|
|
||||||
-- The purpose of this test case is to demonstrate that
|
-- The purpose of this test case is to demonstrate that
|
||||||
-- basic metatable operations on non-table types work.
|
-- basic metatable operations on non-table types work.
|
||||||
-- i.e. that s.sub(s,...) could be used in place of string.sub(s,...)
|
-- i.e. that s.sub(s,...) could be used in place of string.sub(s,...)
|
||||||
local s = "hello"
|
local s = "hello"
|
||||||
print(s:sub(2,4))
|
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)
|
||||||
|
|||||||
@@ -1,18 +1,6 @@
|
|||||||
-- unit tests for require() function
|
-- unit tests for require() function
|
||||||
local ids = {}
|
package.path = "?.lua;src/test/res/?.lua"
|
||||||
local ti = table.insert
|
require 'ids'
|
||||||
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
|
|
||||||
|
|
||||||
-- tests on require
|
-- tests on require
|
||||||
package.path='?.lua;src/test/res/?.lua'
|
package.path='?.lua;src/test/res/?.lua'
|
||||||
|
|||||||
Reference in New Issue
Block a user