Improve __eq metatag processing.
This commit is contained in:
@@ -70,9 +70,4 @@ public class LuaBoolean extends LuaValue {
|
|||||||
public LuaValue getmetatable() {
|
public LuaValue getmetatable() {
|
||||||
return s_metatable;
|
return s_metatable;
|
||||||
}
|
}
|
||||||
|
|
||||||
// equality
|
|
||||||
public boolean eq_b( LuaValue val ) {
|
|
||||||
return this == val || (s_metatable!=null && val.isboolean() && LuaValue.eqmtcall(this, val, s_metatable));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,8 @@ public class LuaDouble extends LuaNumber {
|
|||||||
public boolean equals(Object o) { return o instanceof LuaDouble? ((LuaDouble)o).v == v: false; }
|
public boolean equals(Object o) { return o instanceof LuaDouble? ((LuaDouble)o).v == v: false; }
|
||||||
|
|
||||||
// equality w/ metatable processing
|
// equality w/ metatable processing
|
||||||
public boolean eq_b( LuaValue val ) { return val.raweq(v) || (s_metatable!=null && val.type()==TNUMBER && LuaValue.eqmtcall(val, this, s_metatable)); }
|
public LuaValue eq( LuaValue val ) { return val.raweq(v)? TRUE: FALSE; }
|
||||||
|
public boolean eq_b( LuaValue val ) { return val.raweq(v); }
|
||||||
|
|
||||||
// equality w/o metatable processing
|
// equality w/o metatable processing
|
||||||
public boolean raweq( LuaValue val ) { return val.raweq(v); }
|
public boolean raweq( LuaValue val ) { return val.raweq(v); }
|
||||||
|
|||||||
@@ -67,9 +67,4 @@ public class LuaFunction extends LuaValue {
|
|||||||
public void setfenv(LuaValue env) {
|
public void setfenv(LuaValue env) {
|
||||||
this.env = env!=null? env: NIL;
|
this.env = env!=null? env: NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// equality
|
|
||||||
public boolean eq_b( LuaValue val ) {
|
|
||||||
return this == val || (s_metatable!=null && val.isfunction() && LuaValue.eqmtcall(this, val, s_metatable));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,8 @@ public class LuaInteger extends LuaNumber {
|
|||||||
public boolean equals(Object o) { return o instanceof LuaInteger? ((LuaInteger)o).v == v: false; }
|
public boolean equals(Object o) { return o instanceof LuaInteger? ((LuaInteger)o).v == v: false; }
|
||||||
|
|
||||||
// equality w/ metatable processing
|
// equality w/ metatable processing
|
||||||
public boolean eq_b( LuaValue val ) { return val.raweq(v) || (s_metatable!=null && val.type()==TNUMBER && LuaValue.eqmtcall(val, this, s_metatable)); }
|
public LuaValue eq( LuaValue val ) { return val.raweq(v)? TRUE: FALSE; }
|
||||||
|
public boolean eq_b( LuaValue val ) { return val.raweq(v); }
|
||||||
|
|
||||||
// equality w/o metatable processing
|
// equality w/o metatable processing
|
||||||
public boolean raweq( LuaValue val ) { return val.raweq(v); }
|
public boolean raweq( LuaValue val ) { return val.raweq(v); }
|
||||||
|
|||||||
@@ -83,8 +83,4 @@ public class LuaNil extends LuaValue {
|
|||||||
public Object optuserdata(Object defval) { return defval; }
|
public Object optuserdata(Object defval) { return defval; }
|
||||||
public Object optuserdata(Class c, Object defval) { return defval; }
|
public Object optuserdata(Class c, Object defval) { return defval; }
|
||||||
public LuaValue optvalue(LuaValue defval) { return defval; }
|
public LuaValue optvalue(LuaValue defval) { return defval; }
|
||||||
|
|
||||||
// equality
|
|
||||||
public LuaValue eq( LuaValue val ) { return this == val? TRUE: FALSE; }
|
|
||||||
public boolean eq_b( LuaValue val ) { return this == val; }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -298,17 +298,8 @@ public class LuaString extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// equality w/ metatable processing
|
// equality w/ metatable processing
|
||||||
public boolean eq_b( LuaValue val ) {
|
public LuaValue eq( LuaValue val ) { return val.raweq(this)? TRUE: FALSE; }
|
||||||
if ( val.raweq(this) ) return true;
|
public boolean eq_b( LuaValue val ) { return val.raweq(this); }
|
||||||
if ( s_metatable == null || val.type()!=TSTRING || s_inmeta) return false;
|
|
||||||
s_inmeta = true;
|
|
||||||
try {
|
|
||||||
return LuaValue.eqmtcall(val, this, s_metatable);
|
|
||||||
} finally {
|
|
||||||
s_inmeta = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static boolean s_inmeta = false;
|
|
||||||
|
|
||||||
// equality w/o metatable processing
|
// equality w/o metatable processing
|
||||||
public boolean raweq( LuaValue val ) {
|
public boolean raweq( LuaValue val ) {
|
||||||
|
|||||||
@@ -577,6 +577,7 @@ public class LuaTable extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// equality w/ metatable processing
|
// equality w/ metatable processing
|
||||||
|
public LuaValue eq( LuaValue val ) { return eq_b(val)? TRUE: FALSE; }
|
||||||
public boolean eq_b( LuaValue val ) {
|
public boolean eq_b( LuaValue val ) {
|
||||||
if ( this == val ) return true;
|
if ( this == val ) return true;
|
||||||
if ( m_metatable == null || !val.istable() ) return false;
|
if ( m_metatable == null || !val.istable() ) return false;
|
||||||
|
|||||||
@@ -242,9 +242,4 @@ public class LuaThread extends LuaValue implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// equality
|
|
||||||
public boolean eq_b( LuaValue val ) {
|
|
||||||
return this == val || (s_metatable!=null && val.isthread() && LuaValue.eqmtcall(this, val, s_metatable));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,8 +105,8 @@ public class LuaUserdata extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// equality w/ metatable processing
|
// equality w/ metatable processing
|
||||||
public LuaValue eq( LuaValue val ) { return val.eq_b(this)? TRUE: FALSE; }
|
public LuaValue eq( LuaValue val ) { return eq_b(val)? TRUE: FALSE; }
|
||||||
public boolean eq_b( LuaUserdata val ) {
|
public boolean eq_b( LuaValue val ) {
|
||||||
if ( val.raweq(this) ) return true;
|
if ( val.raweq(this) ) return true;
|
||||||
if ( m_metatable == null || !val.isuserdata() ) return false;
|
if ( m_metatable == null || !val.isuserdata() ) return false;
|
||||||
LuaValue valmt = val.getmetatable();
|
LuaValue valmt = val.getmetatable();
|
||||||
|
|||||||
@@ -256,8 +256,8 @@ public class LuaValue extends Varargs {
|
|||||||
public boolean equals(Object obj) { return this == obj; }
|
public boolean equals(Object obj) { return this == obj; }
|
||||||
|
|
||||||
// arithmetic equality with metatag processing
|
// arithmetic equality with metatag processing
|
||||||
public LuaValue eq( LuaValue val ) { return eq_b(val)? TRUE: FALSE; }
|
public LuaValue eq( LuaValue val ) { return this == val? TRUE: FALSE; }
|
||||||
public boolean eq_b( LuaValue val ) { return false; }
|
public boolean eq_b( LuaValue val ) { return this == val; }
|
||||||
public LuaValue neq( LuaValue val ) { return eq_b(val)? FALSE: TRUE; }
|
public LuaValue neq( LuaValue val ) { return eq_b(val)? FALSE: TRUE; }
|
||||||
public boolean neq_b( LuaValue val ) { return !eq_b(val); }
|
public boolean neq_b( LuaValue val ) { return !eq_b(val); }
|
||||||
|
|
||||||
@@ -273,10 +273,6 @@ public class LuaValue extends Varargs {
|
|||||||
LuaValue h = lhsmt.rawget(EQ);
|
LuaValue h = lhsmt.rawget(EQ);
|
||||||
return h.isnil() || h!=rhsmt.rawget(EQ)? false: h.call(lhs,rhs).toboolean();
|
return h.isnil() || h!=rhsmt.rawget(EQ)? false: h.call(lhs,rhs).toboolean();
|
||||||
}
|
}
|
||||||
public static final boolean eqmtcall(LuaValue lhs, LuaValue rhs, LuaValue sharedmt) {
|
|
||||||
LuaValue h = sharedmt.rawget(EQ);
|
|
||||||
return h.isnil()? false: h.call(lhs,rhs).toboolean();
|
|
||||||
}
|
|
||||||
|
|
||||||
// arithmetic operators
|
// arithmetic operators
|
||||||
public LuaValue add( LuaValue rhs ) { return arithmt(ADD,rhs); }
|
public LuaValue add( LuaValue rhs ) { return arithmt(ADD,rhs); }
|
||||||
|
|||||||
@@ -303,9 +303,11 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
|||||||
case 17: { // "tostring", // (e) -> value
|
case 17: { // "tostring", // (e) -> value
|
||||||
LuaValue arg = args.checkvalue(1);
|
LuaValue arg = args.checkvalue(1);
|
||||||
LuaValue h = arg.metatag(TOSTRING);
|
LuaValue h = arg.metatag(TOSTRING);
|
||||||
if ( ! h.isnil() ) return h.call(arg);
|
if ( ! h.isnil() )
|
||||||
|
return h.call(arg);
|
||||||
LuaValue v = arg.tostring();
|
LuaValue v = arg.tostring();
|
||||||
if ( ! v.isnil() ) return v;
|
if ( ! v.isnil() )
|
||||||
|
return v;
|
||||||
return valueOf(arg.tojstring());
|
return valueOf(arg.tojstring());
|
||||||
}
|
}
|
||||||
case 18: { // "tonumber", // (e [,base]) -> value
|
case 18: { // "tonumber", // (e [,base]) -> value
|
||||||
|
|||||||
@@ -235,6 +235,10 @@ public class UnaryBinaryOperatorsTest extends TestCase {
|
|||||||
LuaValue tbl = new LuaTable();
|
LuaValue tbl = new LuaTable();
|
||||||
LuaValue tbl2 = new LuaTable();
|
LuaValue tbl2 = new LuaTable();
|
||||||
LuaValue tbl3 = new LuaTable();
|
LuaValue tbl3 = new LuaTable();
|
||||||
|
LuaValue uda = new LuaUserdata(new Object());
|
||||||
|
LuaValue udb = new LuaUserdata(uda.touserdata());
|
||||||
|
LuaValue uda2 = new LuaUserdata(new Object());
|
||||||
|
LuaValue uda3 = new LuaUserdata(uda.touserdata());
|
||||||
LuaValue nilb = LuaValue.valueOf( LuaValue.NIL.toboolean() );
|
LuaValue nilb = LuaValue.valueOf( LuaValue.NIL.toboolean() );
|
||||||
LuaValue oneb = LuaValue.valueOf( LuaValue.ONE.toboolean() );
|
LuaValue oneb = LuaValue.valueOf( LuaValue.ONE.toboolean() );
|
||||||
assertEquals( LuaValue.FALSE, nilb );
|
assertEquals( LuaValue.FALSE, nilb );
|
||||||
@@ -247,26 +251,30 @@ public class UnaryBinaryOperatorsTest extends TestCase {
|
|||||||
LuaString.s_metatable = LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } );
|
LuaString.s_metatable = LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } );
|
||||||
tbl.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } ));
|
tbl.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } ));
|
||||||
tbl2.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } ));
|
tbl2.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } ));
|
||||||
|
uda.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } ));
|
||||||
|
udb.setmetatable(uda.getmetatable());
|
||||||
|
uda2.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } ));
|
||||||
// diff metatag function
|
// diff metatag function
|
||||||
tbl3.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } ));
|
tbl3.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } ));
|
||||||
|
uda3.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } ));
|
||||||
|
|
||||||
// same type, same value, does not invoke metatag op
|
// primitive types or same valu do not invoke metatag as per C implementation
|
||||||
assertEquals( tru, tru.eq(tru) );
|
assertEquals( tru, tru.eq(tru) );
|
||||||
assertEquals( tru, tbl.eq(tbl) );
|
|
||||||
assertEquals( tru, one.eq(one) );
|
assertEquals( tru, one.eq(one) );
|
||||||
// same type, different value, same metatag op. comparabile via metatag op
|
assertEquals( tru, abc.eq(abc) );
|
||||||
assertEquals( nilb, tbl.eq(tbl2) );
|
assertEquals( tru, tbl.eq(tbl) );
|
||||||
assertEquals( nilb, tbl2.eq(tbl) );
|
assertEquals( tru, uda.eq(uda) );
|
||||||
assertEquals( nilb, tru.eq(fal) );
|
assertEquals( tru, uda.eq(udb) );
|
||||||
assertEquals( nilb, fal.eq(tru) );
|
assertEquals( fal, tru.eq(fal) );
|
||||||
assertEquals( nilb, zer.eq(one) );
|
assertEquals( fal, fal.eq(tru) );
|
||||||
assertEquals( nilb, one.eq(zer) );
|
assertEquals( fal, zer.eq(one) );
|
||||||
assertEquals( nilb, pi.eq(ee) );
|
assertEquals( fal, one.eq(zer) );
|
||||||
assertEquals( nilb, ee.eq(pi) );
|
assertEquals( fal, pi.eq(ee) );
|
||||||
assertEquals( nilb, pi.eq(one) );
|
assertEquals( fal, ee.eq(pi) );
|
||||||
assertEquals( nilb, one.eq(pi) );
|
assertEquals( fal, pi.eq(one) );
|
||||||
assertEquals( nilb, abc.eq(def) );
|
assertEquals( fal, one.eq(pi) );
|
||||||
assertEquals( nilb, def.eq(abc) );
|
assertEquals( fal, abc.eq(def) );
|
||||||
|
assertEquals( fal, def.eq(abc) );
|
||||||
// different types. not comparable
|
// different types. not comparable
|
||||||
assertEquals( fal, fal.eq(tbl) );
|
assertEquals( fal, fal.eq(tbl) );
|
||||||
assertEquals( fal, tbl.eq(fal) );
|
assertEquals( fal, tbl.eq(fal) );
|
||||||
@@ -276,9 +284,20 @@ public class UnaryBinaryOperatorsTest extends TestCase {
|
|||||||
assertEquals( fal, one.eq(fal) );
|
assertEquals( fal, one.eq(fal) );
|
||||||
assertEquals( fal, abc.eq(one) );
|
assertEquals( fal, abc.eq(one) );
|
||||||
assertEquals( fal, one.eq(abc) );
|
assertEquals( fal, one.eq(abc) );
|
||||||
|
assertEquals( fal, tbl.eq(uda) );
|
||||||
|
assertEquals( fal, uda.eq(tbl) );
|
||||||
|
// same type, same value, does not invoke metatag op
|
||||||
|
assertEquals( tru, tbl.eq(tbl) );
|
||||||
|
// same type, different value, same metatag op. comparabile via metatag op
|
||||||
|
assertEquals( nilb, tbl.eq(tbl2) );
|
||||||
|
assertEquals( nilb, tbl2.eq(tbl) );
|
||||||
|
assertEquals( nilb, uda.eq(uda2) );
|
||||||
|
assertEquals( nilb, uda2.eq(uda) );
|
||||||
// same type, different metatag ops. not comparable
|
// same type, different metatag ops. not comparable
|
||||||
assertEquals( fal, tbl.eq(tbl3) );
|
assertEquals( fal, tbl.eq(tbl3) );
|
||||||
assertEquals( fal, tbl3.eq(tbl) );
|
assertEquals( fal, tbl3.eq(tbl) );
|
||||||
|
assertEquals( fal, uda.eq(uda3) );
|
||||||
|
assertEquals( fal, uda3.eq(uda) );
|
||||||
|
|
||||||
// always use right argument
|
// always use right argument
|
||||||
LuaBoolean.s_metatable = LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } );
|
LuaBoolean.s_metatable = LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } );
|
||||||
@@ -286,26 +305,30 @@ public class UnaryBinaryOperatorsTest extends TestCase {
|
|||||||
LuaString.s_metatable = LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } );
|
LuaString.s_metatable = LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } );
|
||||||
tbl.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } ));
|
tbl.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } ));
|
||||||
tbl2.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } ));
|
tbl2.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } ));
|
||||||
|
uda.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } ));
|
||||||
|
udb.setmetatable(uda.getmetatable());
|
||||||
|
uda2.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } ));
|
||||||
// diff metatag function
|
// diff metatag function
|
||||||
tbl3.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } ));
|
tbl3.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } ));
|
||||||
|
uda3.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } ));
|
||||||
|
|
||||||
// same type, same value, does not invoke metatag op
|
// primitive types or same value do not invoke metatag as per C implementation
|
||||||
assertEquals( tru, tru.eq(tru) );
|
assertEquals( tru, tru.eq(tru) );
|
||||||
assertEquals( tru, tbl.eq(tbl) );
|
|
||||||
assertEquals( tru, one.eq(one) );
|
assertEquals( tru, one.eq(one) );
|
||||||
// same type, different value, same metatag op. comparabile via metatag op
|
assertEquals( tru, abc.eq(abc) );
|
||||||
assertEquals( oneb, tbl.eq(tbl2) );
|
assertEquals( tru, tbl.eq(tbl) );
|
||||||
assertEquals( oneb, tbl2.eq(tbl) );
|
assertEquals( tru, uda.eq(uda) );
|
||||||
assertEquals( oneb, tru.eq(fal) );
|
assertEquals( tru, uda.eq(udb) );
|
||||||
assertEquals( oneb, fal.eq(tru) );
|
assertEquals( fal, tru.eq(fal) );
|
||||||
assertEquals( oneb, zer.eq(one) );
|
assertEquals( fal, fal.eq(tru) );
|
||||||
assertEquals( oneb, one.eq(zer) );
|
assertEquals( fal, zer.eq(one) );
|
||||||
assertEquals( oneb, pi.eq(ee) );
|
assertEquals( fal, one.eq(zer) );
|
||||||
assertEquals( oneb, ee.eq(pi) );
|
assertEquals( fal, pi.eq(ee) );
|
||||||
assertEquals( oneb, pi.eq(one) );
|
assertEquals( fal, ee.eq(pi) );
|
||||||
assertEquals( oneb, one.eq(pi) );
|
assertEquals( fal, pi.eq(one) );
|
||||||
assertEquals( oneb, abc.eq(def) );
|
assertEquals( fal, one.eq(pi) );
|
||||||
assertEquals( oneb, def.eq(abc) );
|
assertEquals( fal, abc.eq(def) );
|
||||||
|
assertEquals( fal, def.eq(abc) );
|
||||||
// different types. not comparable
|
// different types. not comparable
|
||||||
assertEquals( fal, fal.eq(tbl) );
|
assertEquals( fal, fal.eq(tbl) );
|
||||||
assertEquals( fal, tbl.eq(fal) );
|
assertEquals( fal, tbl.eq(fal) );
|
||||||
@@ -315,9 +338,20 @@ public class UnaryBinaryOperatorsTest extends TestCase {
|
|||||||
assertEquals( fal, one.eq(fal) );
|
assertEquals( fal, one.eq(fal) );
|
||||||
assertEquals( fal, abc.eq(one) );
|
assertEquals( fal, abc.eq(one) );
|
||||||
assertEquals( fal, one.eq(abc) );
|
assertEquals( fal, one.eq(abc) );
|
||||||
|
assertEquals( fal, tbl.eq(uda) );
|
||||||
|
assertEquals( fal, uda.eq(tbl) );
|
||||||
|
// same type, same value, does not invoke metatag op
|
||||||
|
assertEquals( tru, tbl.eq(tbl) );
|
||||||
|
// same type, different value, same metatag op. comparabile via metatag op
|
||||||
|
assertEquals( oneb, tbl.eq(tbl2) );
|
||||||
|
assertEquals( oneb, tbl2.eq(tbl) );
|
||||||
|
assertEquals( oneb, uda.eq(uda2) );
|
||||||
|
assertEquals( oneb, uda2.eq(uda) );
|
||||||
// same type, different metatag ops. not comparable
|
// same type, different metatag ops. not comparable
|
||||||
assertEquals( fal, tbl.eq(tbl3) );
|
assertEquals( fal, tbl.eq(tbl3) );
|
||||||
assertEquals( fal, tbl3.eq(tbl) );
|
assertEquals( fal, tbl3.eq(tbl) );
|
||||||
|
assertEquals( fal, uda.eq(uda3) );
|
||||||
|
assertEquals( fal, uda3.eq(uda) );
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
LuaBoolean.s_metatable = null;
|
LuaBoolean.s_metatable = null;
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
print( '---- initial metatables' )
|
local anumber,bnumber = 111,23.45
|
||||||
local anumber = 111
|
local astring,bstring = "abc","def"
|
||||||
local aboolean = false
|
local anumstr,bnumstr = tostring(anumber),tostring(bnumber)
|
||||||
local afunction = function() end
|
local aboolean,bboolean = false,true
|
||||||
local athread = coroutine.create( afunction )
|
local afunction,bfunction = function() end, function() end
|
||||||
local atable = {}
|
local athread,bthead = coroutine.create(afunction),coroutine.create(bfunction)
|
||||||
|
local atable,btable = {},{}
|
||||||
local values = { anumber, aboolean, afunction, athread, atable }
|
local values = { anumber, aboolean, afunction, athread, atable }
|
||||||
for i=1,#values do
|
local groups
|
||||||
print( debug.getmetatable( values[i] ) )
|
|
||||||
end
|
|
||||||
local ts = tostring
|
local ts = tostring
|
||||||
local tb,count = {},0
|
local tb,count = {},0
|
||||||
|
|
||||||
tostring = function(o)
|
tostring = function(o)
|
||||||
local t = type(o)
|
local t = type(o)
|
||||||
if t~='thread' and t~='function' and t~='table' then return ts(o) end
|
if t~='thread' and t~='function' and t~='table' then return ts(o) end
|
||||||
@@ -21,11 +21,23 @@ tostring = function(o)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local buildop = function(name)
|
local buildop = function(name)
|
||||||
|
return function(a,b)
|
||||||
|
print( 'mt.__'..name..'()', a, b )
|
||||||
|
return '__'..name..'-result'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local buildop3 = function(name)
|
||||||
return function(a,b,c)
|
return function(a,b,c)
|
||||||
print( 'mt.__'..name..'()', a, b, c )
|
print( 'mt.__'..name..'()', a, b, c )
|
||||||
return '__'..name..'-result'
|
return '__'..name..'-result'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
local buildop1 = function(name)
|
||||||
|
return function(a)
|
||||||
|
print( 'mt.__'..name..'()', a )
|
||||||
|
return '__'..name..'-result'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local mt = {
|
local mt = {
|
||||||
__call=buildop('call'),
|
__call=buildop('call'),
|
||||||
@@ -35,17 +47,12 @@ local mt = {
|
|||||||
__div=buildop('div'),
|
__div=buildop('div'),
|
||||||
__pow=buildop('pow'),
|
__pow=buildop('pow'),
|
||||||
__mod=buildop('mod'),
|
__mod=buildop('mod'),
|
||||||
__unm=buildop('unm'),
|
__unm=buildop1('unm'),
|
||||||
__len=buildop('neg'),
|
__len=buildop1('len'),
|
||||||
__eq=buildop('eq'),
|
|
||||||
__lt=buildop('lt'),
|
__lt=buildop('lt'),
|
||||||
__le=buildop('le'),
|
__le=buildop('le'),
|
||||||
__tostring=function(a,b)
|
|
||||||
return 'mt.__tostring('..type(a)..','..type(b)..')'
|
|
||||||
end,
|
|
||||||
__metatable={},
|
|
||||||
__index=buildop('index'),
|
__index=buildop('index'),
|
||||||
__newindex=buildop('newindex'),
|
__newindex=buildop3('newindex'),
|
||||||
__concat=buildop('concat'),
|
__concat=buildop('concat'),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,9 +63,48 @@ ecall = function(pattern, ...)
|
|||||||
return s,e
|
return s,e
|
||||||
end
|
end
|
||||||
|
|
||||||
|
print( '---- __eq same types' )
|
||||||
|
local eqmt = { __eq=buildop('eq'), }
|
||||||
|
groups = { {nil,nil}, {true,false}, {123,456}, {11,5.5}, {afunction,bfunction}, {athread,bthread}, {astring,bstring}, {anumber,anumstr} }
|
||||||
|
for i=1,#groups do
|
||||||
|
local a,b = groups[i][1], groups[i][2]
|
||||||
|
local amt,bmt = debug.getmetatable(a),debug.getmetatable(b)
|
||||||
|
print( type(a), type(b), 'before', pcall( function() return a==b end ) )
|
||||||
|
print( type(a), type(b), 'before', pcall( function() return a~=b end ) )
|
||||||
|
print( debug.setmetatable( a, eqmt ) )
|
||||||
|
print( debug.setmetatable( b, eqmt ) )
|
||||||
|
print( type(a), type(b), 'after', pcall( function() return a==b end ) )
|
||||||
|
print( type(a), type(b), 'after', pcall( function() return a~=b end ) )
|
||||||
|
print( debug.setmetatable( a, amt ) )
|
||||||
|
print( debug.setmetatable( b, bmt ) )
|
||||||
|
end
|
||||||
|
|
||||||
|
print( '---- __eq, tables - should invoke metatag comparison' )
|
||||||
|
groups = { {atable,btable} }
|
||||||
|
for i=1,#groups do
|
||||||
|
local a,b = groups[i][1], groups[i][2]
|
||||||
|
local amt,bmt = debug.getmetatable(a),debug.getmetatable(b)
|
||||||
|
print( type(a), type(b), 'before', pcall( function() return a==b end ) )
|
||||||
|
print( type(a), type(b), 'before', pcall( function() return a~=b end ) )
|
||||||
|
print( debug.setmetatable( a, eqmt ) )
|
||||||
|
print( debug.setmetatable( b, eqmt ) )
|
||||||
|
print( type(a), type(b), 'after-a', pcall( function() return a==b end ) )
|
||||||
|
print( type(a), type(b), 'after-a', pcall( function() return a~=b end ) )
|
||||||
|
print( debug.setmetatable( a, amt ) )
|
||||||
|
print( debug.setmetatable( b, bmt ) )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
print( 'nilmt', debug.getmetatable(nil) )
|
||||||
|
print( 'boolmt', debug.getmetatable(true) )
|
||||||
|
print( 'number', debug.getmetatable(1) )
|
||||||
|
print( 'function', debug.getmetatable(afunction) )
|
||||||
|
print( 'thread', debug.getmetatable(athread) )
|
||||||
|
|
||||||
print( '---- __call' )
|
print( '---- __call' )
|
||||||
for i=1,#values do
|
for i=1,#values do
|
||||||
local a = values[i]
|
local a = values[i]
|
||||||
|
local amt = debug.getmetatable(a)
|
||||||
print( type(a), 'before', ecall( 'attempt to call', function() return a('a','b') end ) )
|
print( type(a), 'before', ecall( 'attempt to call', function() return a('a','b') end ) )
|
||||||
print( debug.setmetatable( a, mt ) )
|
print( debug.setmetatable( a, mt ) )
|
||||||
print( type(a), 'after', pcall( function() return a() end ) )
|
print( type(a), 'after', pcall( function() return a() end ) )
|
||||||
@@ -66,13 +112,14 @@ for i=1,#values do
|
|||||||
print( type(a), 'after', pcall( function() return a('a','b') end ) )
|
print( type(a), 'after', pcall( function() return a('a','b') end ) )
|
||||||
print( type(a), 'after', pcall( function() return a('a','b','c') end ) )
|
print( type(a), 'after', pcall( function() return a('a','b','c') end ) )
|
||||||
print( type(a), 'after', pcall( function() return a('a','b','c','d') end ) )
|
print( type(a), 'after', pcall( function() return a('a','b','c','d') end ) )
|
||||||
print( debug.setmetatable( a, nil ) )
|
print( debug.setmetatable( a, amt ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
print( '---- __add, __sub, __mul, __div, __pow, __mod' )
|
print( '---- __add, __sub, __mul, __div, __pow, __mod' )
|
||||||
local groups = { {aboolean, aboolean}, {aboolean, athread}, {aboolean, afunction}, {aboolean, "abc"}, {aboolean, atable} }
|
local groups = { {aboolean, aboolean}, {aboolean, athread}, {aboolean, afunction}, {aboolean, "abc"}, {aboolean, atable} }
|
||||||
for i=1,#groups do
|
for i=1,#groups do
|
||||||
local a,b = groups[i][1], groups[i][2]
|
local a,b = groups[i][1], groups[i][2]
|
||||||
|
local amt,bmt = debug.getmetatable(a),debug.getmetatable(b)
|
||||||
print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return a+b end ) )
|
print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return a+b end ) )
|
||||||
print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return b+a end ) )
|
print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return b+a end ) )
|
||||||
print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return a-b end ) )
|
print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return a-b end ) )
|
||||||
@@ -94,29 +141,33 @@ for i=1,#groups do
|
|||||||
print( type(a), type(b), 'after', pcall( function() return b^a end ) )
|
print( type(a), type(b), 'after', pcall( function() return b^a end ) )
|
||||||
print( type(a), type(b), 'after', pcall( function() return a%b end ) )
|
print( type(a), type(b), 'after', pcall( function() return a%b end ) )
|
||||||
print( type(a), type(b), 'after', pcall( function() return b%a end ) )
|
print( type(a), type(b), 'after', pcall( function() return b%a end ) )
|
||||||
print( debug.setmetatable( a, nil ) )
|
print( debug.setmetatable( a, amt ) )
|
||||||
|
print( debug.setmetatable( b, bmt ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
print( '---- __len' )
|
print( '---- __len' )
|
||||||
values = { aboolean, afunction, athread }
|
values = { aboolean, afunction, athread, anumber }
|
||||||
for i=1,#values do
|
for i=1,#values do
|
||||||
local a = values[i]
|
local a = values[i]
|
||||||
|
local amt = debug.getmetatable(a)
|
||||||
print( type(a), 'before', ecall( 'attempt to get length of ', function() return #a end ) )
|
print( type(a), 'before', ecall( 'attempt to get length of ', function() return #a end ) )
|
||||||
print( debug.setmetatable( a, mt ) )
|
print( debug.setmetatable( a, mt ) )
|
||||||
print( type(a), 'after', pcall( function() return #a end ) )
|
print( type(a), 'after', pcall( function() return #a end ) )
|
||||||
print( debug.setmetatable( a, nil ) )
|
print( debug.setmetatable( a, amt ) )
|
||||||
end
|
end
|
||||||
|
--
|
||||||
print( '---- __neg' )
|
print( '---- __neg' )
|
||||||
values = { aboolean, afunction, athread, "abcd", atable }
|
values = { aboolean, afunction, athread, "abcd", atable, anumber }
|
||||||
for i=1,#values do
|
for i=1,#values do
|
||||||
print( type(values[i]), 'before', ecall( 'attempt to get length of ', function() return #values[i] end ) )
|
local a = values[i]
|
||||||
print( debug.setmetatable( values[i], mt ) )
|
local amt = debug.getmetatable(a)
|
||||||
print( type(values[i]), 'after', pcall( function() return #values[i] end ) )
|
print( type(v), 'before', ecall( 'attempt to perform arithmetic ', function() return -a end ) )
|
||||||
print( debug.setmetatable( values[i], nil ) )
|
print( debug.setmetatable( a, mt ) )
|
||||||
|
print( type(v), 'after', pcall( function() return -a end ) )
|
||||||
|
print( debug.setmetatable( a, amt ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
print( '---- __eq, __lt, __le, same types' )
|
print( '---- __lt, __le, same types' )
|
||||||
local bfunction = function() end
|
local bfunction = function() end
|
||||||
local bthread = coroutine.create( bfunction )
|
local bthread = coroutine.create( bfunction )
|
||||||
local btable = {}
|
local btable = {}
|
||||||
@@ -124,69 +175,59 @@ local groups
|
|||||||
groups = { {true, true}, {true, false}, {afunction, bfunction}, {athread, bthread}, {atable, atable}, {atable, btable} }
|
groups = { {true, true}, {true, false}, {afunction, bfunction}, {athread, bthread}, {atable, atable}, {atable, btable} }
|
||||||
for i=1,#groups do
|
for i=1,#groups do
|
||||||
local a,b = groups[i][1], groups[i][2]
|
local a,b = groups[i][1], groups[i][2]
|
||||||
print( type(a), type(b), 'before', pcall( function() return a==b end ) )
|
local amt,bmt = debug.getmetatable(a),debug.getmetatable(b)
|
||||||
print( type(a), type(b), 'before', pcall( function() return a~=b end ) )
|
|
||||||
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a<b end ) )
|
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a<b end ) )
|
||||||
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a<=b end ) )
|
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a<=b end ) )
|
||||||
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a>b end ) )
|
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a>b end ) )
|
||||||
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a>=b end ) )
|
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a>=b end ) )
|
||||||
print( debug.setmetatable( a, mt ) )
|
print( debug.setmetatable( a, mt ) )
|
||||||
print( debug.setmetatable( b, mt ) )
|
print( debug.setmetatable( b, mt ) )
|
||||||
print( type(a), type(b), 'after', pcall( function() return a==b end ) )
|
|
||||||
print( type(a), type(b), 'after', pcall( function() return a~=b end ) )
|
|
||||||
print( type(a), type(b), 'after', pcall( function() return a<b end ) )
|
print( type(a), type(b), 'after', pcall( function() return a<b end ) )
|
||||||
print( type(a), type(b), 'after', pcall( function() return a<=b end ) )
|
print( type(a), type(b), 'after', pcall( function() return a<=b end ) )
|
||||||
print( type(a), type(b), 'after', pcall( function() return a>b end ) )
|
print( type(a), type(b), 'after', pcall( function() return a>b end ) )
|
||||||
print( type(a), type(b), 'after', pcall( function() return a>=b end ) )
|
print( type(a), type(b), 'after', pcall( function() return a>=b end ) )
|
||||||
print( debug.setmetatable( a, nil ) )
|
print( debug.setmetatable( a, amt ) )
|
||||||
print( debug.setmetatable( b, nil ) )
|
print( debug.setmetatable( b, bmt ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
print( '---- __eq, __lt, __le, different types' )
|
print( '---- __lt, __le, different types' )
|
||||||
groups = { {aboolean, athread}, }
|
groups = { {aboolean, athread}, }
|
||||||
for i=1,#groups do
|
for i=1,#groups do
|
||||||
local a,b = groups[i][1], groups[i][2]
|
local a,b = groups[i][1], groups[i][2]
|
||||||
print( type(a), type(b), 'before', pcall( function() return a==b end ) )
|
local amt,bmt = debug.getmetatable(a),debug.getmetatable(b)
|
||||||
print( type(a), type(b), 'before', pcall( function() return a~=b end ) )
|
|
||||||
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a<b end ) )
|
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a<b end ) )
|
||||||
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a<=b end ) )
|
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a<=b end ) )
|
||||||
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a>b end ) )
|
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a>b end ) )
|
||||||
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a>=b end ) )
|
print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a>=b end ) )
|
||||||
print( debug.setmetatable( a, mt ) )
|
print( debug.setmetatable( a, mt ) )
|
||||||
print( debug.setmetatable( b, mt ) )
|
print( debug.setmetatable( b, mt ) )
|
||||||
print( type(a), type(b), 'after-a', pcall( function() return a==b end ) )
|
|
||||||
print( type(a), type(b), 'after-a', pcall( function() return a~=b end ) )
|
|
||||||
print( type(a), type(b), 'after-a', ecall( 'attempt to compare', function() return a<b end ) )
|
print( type(a), type(b), 'after-a', ecall( 'attempt to compare', function() return a<b end ) )
|
||||||
print( type(a), type(b), 'after-a', ecall( 'attempt to compare', function() return a<=b end ) )
|
print( type(a), type(b), 'after-a', ecall( 'attempt to compare', function() return a<=b end ) )
|
||||||
print( type(a), type(b), 'after-a', ecall( 'attempt to compare', function() return a>b end ) )
|
print( type(a), type(b), 'after-a', ecall( 'attempt to compare', function() return a>b end ) )
|
||||||
print( type(a), type(b), 'after-a', ecall( 'attempt to compare', function() return a>=b end ) )
|
print( type(a), type(b), 'after-a', ecall( 'attempt to compare', function() return a>=b end ) )
|
||||||
print( debug.setmetatable( a, nil ) )
|
print( debug.setmetatable( a, amt ) )
|
||||||
print( debug.setmetatable( b, nil ) )
|
print( debug.setmetatable( b, bmt ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
print( '---- __tostring' )
|
print( '---- __tostring' )
|
||||||
values = { aboolean, afunction, athread, atable, "abc" }
|
values = { aboolean, afunction, athread, atable, "abc" }
|
||||||
|
local strmt = { __tostring=function(a)
|
||||||
|
return 'mt.__tostring('..type(a)..')'
|
||||||
|
end,
|
||||||
|
}
|
||||||
for i=1,#values do
|
for i=1,#values do
|
||||||
local a = values[i]
|
local a = values[i]
|
||||||
print( debug.setmetatable( a, mt ) )
|
local amt = debug.getmetatable(a)
|
||||||
|
print( debug.setmetatable( a, strmt ) )
|
||||||
print( type(a), 'after', pcall( function() return ts(a) end ) )
|
print( type(a), 'after', pcall( function() return ts(a) end ) )
|
||||||
print( debug.setmetatable( a, nil ) )
|
print( debug.setmetatable( a, amt ) )
|
||||||
end
|
|
||||||
|
|
||||||
print( '---- __metatable' )
|
|
||||||
values = { aboolean, afunction, athread, atable, "abc" }
|
|
||||||
for i=1,#values do
|
|
||||||
local a = values[i]
|
|
||||||
print( type(a), 'before', pcall( function() return debug.getmetatable(a), getmetatable(a) end ) )
|
|
||||||
print( debug.setmetatable( a, mt ) )
|
|
||||||
print( type(a), 'after', pcall( function() return debug.getmetatable(a), getmetatable(a) end ) )
|
|
||||||
print( debug.setmetatable( a, nil ) )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
print( '---- __index, __newindex' )
|
print( '---- __index, __newindex' )
|
||||||
values = { aboolean, anumber, afunction, athread }
|
values = { aboolean, anumber, afunction, athread }
|
||||||
for i=1,#values do
|
for i=1,#values do
|
||||||
local a = values[i]
|
local a = values[i]
|
||||||
|
local amt = debug.getmetatable(a)
|
||||||
print( type(a), 'before', ecall( 'attempt to index', function() return a.foo end ) )
|
print( type(a), 'before', ecall( 'attempt to index', function() return a.foo end ) )
|
||||||
print( type(a), 'before', ecall( 'attempt to index', function() return a[123] end ) )
|
print( type(a), 'before', ecall( 'attempt to index', function() return a[123] end ) )
|
||||||
print( type(a), 'before', ecall( 'index', function() a.foo = 'bar' end ) )
|
print( type(a), 'before', ecall( 'index', function() a.foo = 'bar' end ) )
|
||||||
@@ -198,7 +239,7 @@ for i=1,#values do
|
|||||||
print( type(a), 'after', pcall( function() a.foo = 'bar' end ) )
|
print( type(a), 'after', pcall( function() a.foo = 'bar' end ) )
|
||||||
print( type(a), 'after', pcall( function() a[123] = 'bar' end ) )
|
print( type(a), 'after', pcall( function() a[123] = 'bar' end ) )
|
||||||
print( type(a), 'after', ecall( 'attempt to call', function() return a:foo() end ) )
|
print( type(a), 'after', ecall( 'attempt to call', function() return a:foo() end ) )
|
||||||
print( debug.setmetatable( a, nil ) )
|
print( debug.setmetatable( a, amt ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
print( '---- __concat' )
|
print( '---- __concat' )
|
||||||
@@ -216,6 +257,7 @@ local concatmt = {
|
|||||||
}
|
}
|
||||||
for i=1,#groups do
|
for i=1,#groups do
|
||||||
local a,b = groups[i][1], groups[i][2]
|
local a,b = groups[i][1], groups[i][2]
|
||||||
|
local amt,bmt = debug.getmetatable(a),debug.getmetatable(b)
|
||||||
print( type(a), type(b), 'before', ecall( 'attempt to concatenate ', function() return a..b end ) )
|
print( type(a), type(b), 'before', ecall( 'attempt to concatenate ', function() return a..b end ) )
|
||||||
print( type(a), type(b), 'before', ecall( 'attempt to concatenate ', function() return b..a end ) )
|
print( type(a), type(b), 'before', ecall( 'attempt to concatenate ', function() return b..a end ) )
|
||||||
print( type(a), type(s), type(t), 'before', ecall( 'attempt to concatenate ', function() return a..s..t end ) )
|
print( type(a), type(s), type(t), 'before', ecall( 'attempt to concatenate ', function() return a..s..t end ) )
|
||||||
@@ -227,6 +269,18 @@ for i=1,#groups do
|
|||||||
print( type(a), type(s), type(t), 'before', pcall( function() return a..s..t end ) )
|
print( type(a), type(s), type(t), 'before', pcall( function() return a..s..t end ) )
|
||||||
print( type(s), type(a), type(t), 'before', ecall( 'attempt to concatenate ', function() return s..a..t end ) )
|
print( type(s), type(a), type(t), 'before', ecall( 'attempt to concatenate ', function() return s..a..t end ) )
|
||||||
print( type(s), type(t), type(a), 'before', ecall( 'attempt to concatenate ', function() return s..t..a end ) )
|
print( type(s), type(t), type(a), 'before', ecall( 'attempt to concatenate ', function() return s..t..a end ) )
|
||||||
print( debug.setmetatable( a, nil ) )
|
print( debug.setmetatable( a, amt ) )
|
||||||
|
print( debug.setmetatable( b, bmt ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
print( '---- __metatable' )
|
||||||
|
values = { aboolean, afunction, athread, atable, "abc" }
|
||||||
|
local mtmt = { __metatable={}, }
|
||||||
|
for i=1,#values do
|
||||||
|
local a = values[i]
|
||||||
|
local amt = debug.getmetatable(a)
|
||||||
|
print( type(a), 'before', pcall( function() return debug.getmetatable(a), getmetatable(a) end ) )
|
||||||
|
print( debug.setmetatable( a, mtmt ) )
|
||||||
|
print( type(a), 'after', pcall( function() return debug.getmetatable(a), getmetatable(a) end ) )
|
||||||
|
print( debug.setmetatable( a, amt ) )
|
||||||
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user