Merge pull request #176 from v-for-vandal/lua_eq
Add default __eq implementation for Lua
This commit is contained in:
commit
c17f77750a
6 changed files with 157 additions and 18 deletions
|
|
@ -210,6 +210,7 @@ CPP_TEST_CASES += \
|
||||||
enum_template \
|
enum_template \
|
||||||
enum_thorough \
|
enum_thorough \
|
||||||
enum_var \
|
enum_var \
|
||||||
|
equality \
|
||||||
evil_diamond \
|
evil_diamond \
|
||||||
evil_diamond_ns \
|
evil_diamond_ns \
|
||||||
evil_diamond_prop \
|
evil_diamond_prop \
|
||||||
|
|
|
||||||
67
Examples/test-suite/equality.i
Normal file
67
Examples/test-suite/equality.i
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* File : equality.i */
|
||||||
|
/*
|
||||||
|
Specific test for operator== overload. Partially overlaps with
|
||||||
|
operator_overload.i
|
||||||
|
*/
|
||||||
|
|
||||||
|
%module equality
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
|
||||||
|
/* Point has no equality operator */
|
||||||
|
typedef struct Point
|
||||||
|
{
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
} Point;
|
||||||
|
|
||||||
|
static const Point s_zeroPoint = { 0.0, 0.0 };
|
||||||
|
/* stack version */
|
||||||
|
Point MakePoint(double x, double y)
|
||||||
|
{ Point new_point = {x, y}; return new_point; }
|
||||||
|
|
||||||
|
const Point* GetZeroPointPtr() { return &s_zeroPoint; }
|
||||||
|
Point GetZeroPointCopy() { return s_zeroPoint; }
|
||||||
|
|
||||||
|
/* EqualOpDefined has correct equality operator */
|
||||||
|
class EqualOpDefined {
|
||||||
|
public:
|
||||||
|
EqualOpDefined():
|
||||||
|
x(5) {}
|
||||||
|
EqualOpDefined(int val):
|
||||||
|
x(val) {}
|
||||||
|
|
||||||
|
int x;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* EqualOpWrong has logically incorrect equality operator */
|
||||||
|
class EqualOpWrong {
|
||||||
|
public:
|
||||||
|
inline static const EqualOpWrong* GetStaticObject();
|
||||||
|
};
|
||||||
|
|
||||||
|
static const EqualOpWrong s_wrongEqOp;
|
||||||
|
|
||||||
|
const EqualOpWrong* EqualOpWrong::GetStaticObject()
|
||||||
|
{ return &s_wrongEqOp; }
|
||||||
|
|
||||||
|
|
||||||
|
inline bool operator==( const EqualOpDefined& first, const EqualOpDefined& second )
|
||||||
|
{ return first.x == second.x; }
|
||||||
|
|
||||||
|
inline bool operator==( const EqualOpWrong& first, const EqualOpWrong& second )
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
/*
|
||||||
|
in order to wrapper this correctly
|
||||||
|
we need to extend the class
|
||||||
|
to make the friends & non members part of the class
|
||||||
|
*/
|
||||||
|
%extend EqualOpDefined {
|
||||||
|
bool operator==(const EqualOpDefined& b){return (*$self) == b;}
|
||||||
|
}
|
||||||
|
%extend EqualOpWrong {
|
||||||
|
bool operator==(const EqualOpWrong& b){return (*$self) == b;}
|
||||||
|
}
|
||||||
|
|
@ -86,3 +86,14 @@ f4_name = tostring(f4)
|
||||||
assert( f2_name == "Foo" )
|
assert( f2_name == "Foo" )
|
||||||
assert( f3_name == "Foo" )
|
assert( f3_name == "Foo" )
|
||||||
assert( f4_name == "FooSubSub" )
|
assert( f4_name == "FooSubSub" )
|
||||||
|
|
||||||
|
-- Test __eq implementation supplied by default
|
||||||
|
|
||||||
|
-- eq_f1 and eq_f2 must be different userdata with same Foo* pointer. If eq_f1 and eq_f2 are the same userdata (e.g.)
|
||||||
|
-- > eq_f1 = smth
|
||||||
|
-- > eq_f2 = eq_f1
|
||||||
|
-- then default Lua equality comparison kicks in and considers them equal. Access to global_fptr is actually a
|
||||||
|
-- function call (internally) and it returns new userdata each time.
|
||||||
|
eq_f1 = cb.Bar.global_fptr
|
||||||
|
eq_f2 = cb.Bar.global_fptr
|
||||||
|
assert( eq_f1 == eq_f2 )
|
||||||
|
|
|
||||||
47
Examples/test-suite/lua/equality_runme.lua
Normal file
47
Examples/test-suite/lua/equality_runme.lua
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
require("import") -- the import fn
|
||||||
|
import("equality") -- import code
|
||||||
|
eq=equality -- renaming import
|
||||||
|
|
||||||
|
-- catch "undefined" global variables
|
||||||
|
local env = _ENV -- Lua 5.2
|
||||||
|
if not env then env = getfenv () end -- Lua 5.1
|
||||||
|
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})
|
||||||
|
|
||||||
|
-- === No equality operator ===
|
||||||
|
|
||||||
|
-- logically same data without equality operator are not equal
|
||||||
|
p1 = eq.MakePoint(10,9);
|
||||||
|
p2 = eq.MakePoint(10,9);
|
||||||
|
|
||||||
|
assert( p1 ~= p2 );
|
||||||
|
|
||||||
|
-- different wrappers for same Point* are equal
|
||||||
|
p3 = eq.GetZeroPointPtr()
|
||||||
|
p4 = eq.GetZeroPointPtr()
|
||||||
|
|
||||||
|
assert( p3 == p4 )
|
||||||
|
|
||||||
|
|
||||||
|
-- === Logically correct equality operator ===
|
||||||
|
|
||||||
|
ed1 = eq.EqualOpDefined(10)
|
||||||
|
ed2 = eq.EqualOpDefined(10)
|
||||||
|
ed3 = eq.EqualOpDefined(15)
|
||||||
|
|
||||||
|
assert( ed1 == ed2 )
|
||||||
|
assert( ed1 ~= ed3 )
|
||||||
|
|
||||||
|
|
||||||
|
-- === Logically incorrect equality operator ===
|
||||||
|
|
||||||
|
ew1 = eq.EqualOpWrong()
|
||||||
|
ew2 = eq.EqualOpWrong()
|
||||||
|
|
||||||
|
assert( ew1 ~= ew2 );
|
||||||
|
|
||||||
|
ew3 = eq.EqualOpWrong.GetStaticObject()
|
||||||
|
ew4 = eq.EqualOpWrong.GetStaticObject()
|
||||||
|
|
||||||
|
-- Even though these are pointers to same object, operator== overload should
|
||||||
|
-- state that they are not equal
|
||||||
|
assert( ew3 ~= ew4 )
|
||||||
|
|
@ -1037,6 +1037,23 @@ SWIGINTERN int SWIG_Lua_class_disown(lua_State *L)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* lua callable function to compare userdata's value
|
||||||
|
the issue is that two userdata may point to the same thing
|
||||||
|
but to lua, they are different objects */
|
||||||
|
SWIGRUNTIME int SWIG_Lua_class_equal(lua_State *L)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
swig_lua_userdata *usr1,*usr2;
|
||||||
|
if (!lua_isuserdata(L,1) || !lua_isuserdata(L,2)) /* just in case */
|
||||||
|
return 0; /* nil reply */
|
||||||
|
usr1=(swig_lua_userdata*)lua_touserdata(L,1); /* get data */
|
||||||
|
usr2=(swig_lua_userdata*)lua_touserdata(L,2); /* get data */
|
||||||
|
/*result=(usr1->ptr==usr2->ptr && usr1->type==usr2->type); only works if type is the same*/
|
||||||
|
result=(usr1->ptr==usr2->ptr);
|
||||||
|
lua_pushboolean(L,result);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* populate table at the top of the stack with metamethods that ought to be inherited */
|
/* populate table at the top of the stack with metamethods that ought to be inherited */
|
||||||
SWIGINTERN void SWIG_Lua_populate_inheritable_metamethods(lua_State *L)
|
SWIGINTERN void SWIG_Lua_populate_inheritable_metamethods(lua_State *L)
|
||||||
{
|
{
|
||||||
|
|
@ -1439,6 +1456,7 @@ SWIGINTERN void SWIG_Lua_add_class_user_metamethods(lua_State *L, swig_lua_class
|
||||||
int metatable_index;
|
int metatable_index;
|
||||||
int metamethods_info_index;
|
int metamethods_info_index;
|
||||||
int tostring_undefined;
|
int tostring_undefined;
|
||||||
|
int eq_undefined = 0;
|
||||||
|
|
||||||
SWIG_Lua_get_class_metatable(L, clss->fqname);
|
SWIG_Lua_get_class_metatable(L, clss->fqname);
|
||||||
metatable_index = lua_gettop(L);
|
metatable_index = lua_gettop(L);
|
||||||
|
|
@ -1471,6 +1489,18 @@ SWIGINTERN void SWIG_Lua_add_class_user_metamethods(lua_State *L, swig_lua_class
|
||||||
lua_pop(L,1); /* remove copy of the key */
|
lua_pop(L,1); /* remove copy of the key */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Special handling for __eq method */
|
||||||
|
lua_pushstring(L, "__eq");
|
||||||
|
lua_pushvalue(L,-1);
|
||||||
|
lua_rawget(L,metatable_index);
|
||||||
|
eq_undefined = lua_isnil(L,-1);
|
||||||
|
lua_pop(L,1);
|
||||||
|
if( eq_undefined ) {
|
||||||
|
lua_pushcfunction(L, SWIG_Lua_class_equal);
|
||||||
|
lua_rawset(L, metatable_index);
|
||||||
|
} else {
|
||||||
|
lua_pop(L,1); /* remove copy of the key */
|
||||||
|
}
|
||||||
/* Warning: __index and __newindex are SWIG-defined. For user-defined operator[]
|
/* Warning: __index and __newindex are SWIG-defined. For user-defined operator[]
|
||||||
* a __getitem/__setitem method should be defined
|
* a __getitem/__setitem method should be defined
|
||||||
*/
|
*/
|
||||||
|
|
@ -1788,23 +1818,6 @@ SWIGRUNTIME int SWIG_Lua_type(lua_State *L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* lua callable function to compare userdata's value
|
|
||||||
the issue is that two userdata may point to the same thing
|
|
||||||
but to lua, they are different objects */
|
|
||||||
SWIGRUNTIME int SWIG_Lua_equal(lua_State *L)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
swig_lua_userdata *usr1,*usr2;
|
|
||||||
if (!lua_isuserdata(L,1) || !lua_isuserdata(L,2)) /* just in case */
|
|
||||||
return 0; /* nil reply */
|
|
||||||
usr1=(swig_lua_userdata*)lua_touserdata(L,1); /* get data */
|
|
||||||
usr2=(swig_lua_userdata*)lua_touserdata(L,2); /* get data */
|
|
||||||
/*result=(usr1->ptr==usr2->ptr && usr1->type==usr2->type); only works if type is the same*/
|
|
||||||
result=(usr1->ptr==usr2->ptr);
|
|
||||||
lua_pushboolean(L,result);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* global variable support code: class/struct typemap functions
|
* global variable support code: class/struct typemap functions
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ SWIGEXPORT int SWIG_init(lua_State* L) /* default Lua action */
|
||||||
#if ((SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUA) && (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC)) || defined(SWIG_LUA_ELUA_EMULATE)
|
#if ((SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUA) && (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC)) || defined(SWIG_LUA_ELUA_EMULATE)
|
||||||
/* add a global fn */
|
/* add a global fn */
|
||||||
SWIG_Lua_add_function(L,"swig_type",SWIG_Lua_type);
|
SWIG_Lua_add_function(L,"swig_type",SWIG_Lua_type);
|
||||||
SWIG_Lua_add_function(L,"swig_equals",SWIG_Lua_equal);
|
SWIG_Lua_add_function(L,"swig_equals",SWIG_Lua_class_equal);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC)
|
#if (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue