nspace.i example is working

This commit is contained in:
Artem Serebriyskiy 2013-10-29 21:14:34 +04:00
commit 295788c8a0
3 changed files with 468 additions and 156 deletions

View file

@ -157,7 +157,8 @@ struct swig_lua_namespace {
}; };
struct swig_lua_class { struct swig_lua_class {
const char *name; const char *name; // Name that this class has in Lua
const char *fqname; // Fully qualified name - Scope + class name
swig_type_info **type; swig_type_info **type;
lua_CFunction constructor; lua_CFunction constructor;
void (*destructor)(void *); void (*destructor)(void *);
@ -511,7 +512,7 @@ SWIGINTERN void SWIG_Lua_class_register(lua_State* L,swig_lua_class* clss);
SWIGINTERN int SWIG_Lua_add_namespace_details(lua_State* L, swig_lua_namespace* ns) SWIGINTERN int SWIG_Lua_add_namespace_details(lua_State* L, swig_lua_namespace* ns)
{ {
int i = 0; int i = 0;
/* There must be table at the top of the stack */ /* There must be namespace table (not metatable) at the top of the stack */
assert(lua_istable(L,-1)); assert(lua_istable(L,-1));
SWIG_Lua_InstallConstants(L, ns->ns_constants); SWIG_Lua_InstallConstants(L, ns->ns_constants);
@ -539,10 +540,13 @@ SWIGINTERN int SWIG_Lua_add_namespace_details(lua_State* L, swig_lua_namespace*
*/ */
SWIGINTERN void SWIG_Lua_add_namespace_classes(lua_State* L, swig_lua_namespace* ns) SWIGINTERN void SWIG_Lua_add_namespace_classes(lua_State* L, swig_lua_namespace* ns)
{ {
// There must be module/namespace table at the top of the stack
assert(lua_istable(L,-1));
swig_lua_class** classes = ns->ns_classes; swig_lua_class** classes = ns->ns_classes;
if( classes != 0 ) { if( classes != 0 ) {
while((*classes)->name != 0) { while(*classes != 0) {
SWIG_Lua_class_register(L, *classes); SWIG_Lua_class_register(L, *classes);
classes++; classes++;
} }
@ -556,6 +560,7 @@ SWIGINTERN void SWIG_Lua_add_namespace_classes(lua_State* L, swig_lua_namespace*
*/ */
SWIGINTERN int SWIG_Lua_namespace_register(lua_State* L, swig_lua_namespace* ns, bool reg) SWIGINTERN int SWIG_Lua_namespace_register(lua_State* L, swig_lua_namespace* ns, bool reg)
{ {
int begin = lua_gettop(L);
assert(lua_istable(L,-1)); /* just in case. This is supposed to be module table or parent namespace table */ assert(lua_istable(L,-1)); /* just in case. This is supposed to be module table or parent namespace table */
lua_checkstack(L,5); lua_checkstack(L,5);
lua_newtable(L); /* namespace itself */ lua_newtable(L); /* namespace itself */
@ -582,11 +587,14 @@ SWIGINTERN int SWIG_Lua_namespace_register(lua_State* L, swig_lua_namespace* ns,
// Register all functions, variables etc // Register all functions, variables etc
SWIG_Lua_add_namespace_details(L,ns); SWIG_Lua_add_namespace_details(L,ns);
// Register classes
SWIG_Lua_add_namespace_classes(L,ns);
swig_lua_namespace** sub_namespace = ns->ns_namespaces; swig_lua_namespace** sub_namespace = ns->ns_namespaces;
if( sub_namespace != 0) { if( sub_namespace != 0) {
while((*sub_namespace)->name != 0) { while(*sub_namespace != 0) {
SWIG_Lua_namespace_register(L, *sub_namespace, true); SWIG_Lua_namespace_register(L, *sub_namespace, true);
lua_pop(L,1); // removing sub-namespace table
sub_namespace++; sub_namespace++;
} }
} }
@ -596,39 +604,45 @@ SWIGINTERN int SWIG_Lua_namespace_register(lua_State* L, swig_lua_namespace* ns,
lua_pushvalue(L,-2); lua_pushvalue(L,-2);
lua_rawset(L,-4); /* add namespace to module table */ lua_rawset(L,-4); /* add namespace to module table */
} }
assert(lua_gettop(L) == begin+1);
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* global variable support code: classes * global variable support code: classes
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
/* the class.get method, performs the lookup of class attributes */ /* the class.get method, performs the lookup of class attributes
* Method can be called from Lua directly and recursively from itself. Thats why
* we can't use absolute stack positions
*/
SWIGINTERN int SWIG_Lua_class_get(lua_State* L) SWIGINTERN int SWIG_Lua_class_get(lua_State* L)
{ {
/* there should be 2 params passed in /* there should be 2 params passed in
(1) userdata (not the meta table) (1) userdata (not the meta table)
(2) string name of the attribute (2) string name of the attribute
*/ */
int base = lua_gettop(L)-2;
lua_checkstack(L,5);
assert(lua_isuserdata(L,-2)); /* just in case */ assert(lua_isuserdata(L,-2)); /* just in case */
lua_getmetatable(L,-2); /* get the meta table */ lua_getmetatable(L,-2); /* get the meta table */
assert(lua_istable(L,-1)); /* just in case */ assert(lua_istable(L,-1)); /* just in case */
SWIG_Lua_get_table(L,".get"); /* find the .get table */ SWIG_Lua_get_table(L,".get"); /* find the .get table */
assert(lua_istable(L,-1)); /* just in case */ assert(lua_istable(L,-1)); /* just in case */
/* look for the key in the .get table */ /* look for the key in the .get table */
lua_pushvalue(L,2); /* key */ lua_pushvalue(L,base+2); /* key */
lua_rawget(L,-2); lua_rawget(L,-2);
lua_remove(L,-2); /* stack tidy, remove .get table */ lua_remove(L,-2); /* stack tidy, remove .get table */
if (lua_iscfunction(L,-1)) if (lua_iscfunction(L,-1))
{ /* found it so call the fn & return its value */ { /* found it so call the fn & return its value */
lua_pushvalue(L,1); /* the userdata */ lua_pushvalue(L,base+1); /* the userdata */
lua_call(L,1,1); /* 1 value in (userdata),1 out (result) */ lua_call(L,1,1); /* 1 value in (userdata),1 out (result) */
lua_remove(L,-2); /* stack tidy, remove metatable */ lua_remove(L,-2); /* stack tidy, remove metatable */
return 1; return 1;
} }
lua_pop(L,1); /* remove whatever was there */ lua_pop(L,1); /* remove whatever was there */
/* ok, so try the .fn table */ /* ok, so try the .fn table */
SWIG_Lua_get_table(L,".fn"); /* find the .get table */ SWIG_Lua_get_table(L,".fn"); /* find the .fn table */
assert(lua_istable(L,-1)); /* just in case */ assert(lua_istable(L,-1)); /* just in case */
lua_pushvalue(L,2); /* key */ lua_pushvalue(L,base+2); /* key */
lua_rawget(L,-2); /* look for the fn */ lua_rawget(L,-2); /* look for the fn */
lua_remove(L,-2); /* stack tidy, remove .fn table */ lua_remove(L,-2); /* stack tidy, remove .fn table */
if (lua_isfunction(L,-1)) /* note: if its a C function or lua function */ if (lua_isfunction(L,-1)) /* note: if its a C function or lua function */
@ -642,60 +656,197 @@ SWIGINTERN int SWIG_Lua_class_get(lua_State* L)
SWIG_Lua_get_table(L,"__getitem"); /* find the __getitem fn */ SWIG_Lua_get_table(L,"__getitem"); /* find the __getitem fn */
if (lua_iscfunction(L,-1)) /* if its there */ if (lua_iscfunction(L,-1)) /* if its there */
{ /* found it so call the fn & return its value */ { /* found it so call the fn & return its value */
lua_pushvalue(L,1); /* the userdata */ lua_pushvalue(L,base+1); /* the userdata */
lua_pushvalue(L,2); /* the parameter */ lua_pushvalue(L,base+2); /* the parameter */
lua_call(L,2,1); /* 2 value in (userdata),1 out (result) */ lua_call(L,2,1); /* 2 value in (userdata),1 out (result) */
lua_remove(L,-2); /* stack tidy, remove metatable */ lua_remove(L,-2); /* stack tidy, remove metatable */
return 1; return 1;
} }
lua_pop(L,1);
// Search in base classes
// TODO: Different for elua_ltr
SWIG_Lua_get_table(L,".bases");
assert(lua_istable(L,-1));
int bases_count = lua_rawlen(L,-1);
if(bases_count>0)
{
int original_metatable = lua_absindex(L,-2);
int i;
int ret = 0; // Number of returned values
lua_pushvalue(L,base+1); // push userdata
lua_pushvalue(L,base+2); // Push key again
// Trick: temporaly replacing original metatable
// with metatable for base class and call getter
for(i=0;i<bases_count;i++) {
lua_rawgeti(L,-3,i+1); // get base metatable here
assert(lua_istable(L,-1));
assert(lua_isuserdata(L,-3));
lua_setmetatable(L,-3); // Set new metatable
assert(lua_isuserdata(L,-2));
ret = SWIG_Lua_class_get(L); // Forward call
assert(ret==0||ret==1);
if(ret>0)
break;
}
// Return original metatable back
lua_pushvalue(L,original_metatable);
lua_setmetatable(L,base+1);
if(ret>0)
{
// tidy stack. Stack currently is:
// --base--
// userdata
// key
// metatable
// .bases table
// userdata
// key : -2
// return value : -1
lua_remove(L,-2); // remove key
lua_remove(L,-2); // remove userdata
lua_remove(L,-2); // remove .bases
lua_remove(L,-2); // remove metatable
return 1;
} else {
lua_pop(L,2); // remove key and userdata
}
}
// Tidy stack:
// --base--
// userdata
// key
// metatable
// .bases table
lua_pop(L,2);
assert(lua_gettop(L)==base+2);
return 0; /* sorry not known */ return 0; /* sorry not known */
} }
/* the class.set method, performs the lookup of class attributes */ /* helper for the class.set method, performs the lookup of class attributes
SWIGINTERN int SWIG_Lua_class_set(lua_State* L) * Method can be called from SWIG_Lua_class_set or recursively from itself
*/
SWIGINTERN int SWIG_Lua_class_do_set(lua_State* L)
{ {
/* there should be 3 params passed in /* there should be 3 params passed in
(1) table (not the meta table) (1) table (not the meta table)
(2) string name of the attribute (2) string name of the attribute
(3) any for the new value (3) any for the new value
printf("SWIG_Lua_class_set %p(%s) '%s' %p(%s)\n", printf("SWIG_Lua_class_set %p(%s) '%s' %p(%s)\n",
lua_topointer(L,1),lua_typename(L,lua_type(L,1)), lua_topointer(L,-3),lua_typename(L,lua_type(L,-3)),
lua_tostring(L,2), lua_tostring(L,-2),
lua_topointer(L,3),lua_typename(L,lua_type(L,3)));*/ lua_topointer(L,-1),lua_typename(L,lua_type(L,-1)));*/
assert(lua_isuserdata(L,1)); /* just in case */ int base = lua_gettop(L) - 3;
lua_getmetatable(L,1); /* get the meta table */ lua_checkstack(L,5);
assert(lua_isuserdata(L,base+1)); /* just in case */
lua_getmetatable(L,base+1); /* get the meta table */
assert(lua_istable(L,-1)); /* just in case */ assert(lua_istable(L,-1)); /* just in case */
SWIG_Lua_get_table(L,".set"); /* find the .set table */ SWIG_Lua_get_table(L,".set"); /* find the .set table */
if (lua_istable(L,-1)) if (lua_istable(L,-1))
{ {
/* look for the key in the .set table */ /* look for the key in the .set table */
lua_pushvalue(L,2); /* key */ lua_pushvalue(L,base+2); /* key */
lua_rawget(L,-2); lua_rawget(L,-2);
lua_remove(L,-2); /* tidy stack, remove .set table */
if (lua_iscfunction(L,-1)) if (lua_iscfunction(L,-1))
{ /* found it so call the fn & return its value */ { /* found it so call the fn & return its value */
lua_pushvalue(L,1); /* userdata */ lua_pushvalue(L,base+1); /* userdata */
lua_pushvalue(L,3); /* value */ lua_pushvalue(L,base+3); /* value */
lua_call(L,2,0); lua_call(L,2,0);
lua_remove(L,base+4); /*remove metatable*/
assert(lua_gettop(L) == base+3); // TODO:REMOVE
return 0; return 0;
} }
lua_pop(L,1); /* remove the value */ lua_pop(L,1); /* remove the value */
} else {
lua_pop(L,1); /* remove the answer for .set table request*/
} }
lua_pop(L,1); /* remove the value .set table */ assert(lua_gettop(L) == base + 4); // TODO: REMOVE
/* NEW: looks for the __setitem() fn /* NEW: looks for the __setitem() fn
this is a user provided set fn */ this is a user provided set fn */
SWIG_Lua_get_table(L,"__setitem"); /* find the fn */ SWIG_Lua_get_table(L,"__setitem"); /* find the fn */
if (lua_iscfunction(L,-1)) /* if its there */ if (lua_iscfunction(L,-1)) /* if its there */
{ /* found it so call the fn & return its value */ { /* found it so call the fn & return its value */
lua_pushvalue(L,1); /* the userdata */ lua_pushvalue(L,base+1); /* the userdata */
lua_pushvalue(L,2); /* the parameter */ lua_pushvalue(L,base+2); /* the parameter */
lua_pushvalue(L,3); /* the value */ lua_pushvalue(L,base+3); /* the value */
lua_call(L,3,0); /* 3 values in ,0 out */ lua_call(L,3,0); /* 3 values in ,0 out */
lua_remove(L,-2); /* stack tidy, remove metatable */ lua_remove(L,-2); /* stack tidy, remove metatable */
return 1; return 0;
}
lua_pop(L,1); // remove value
assert(lua_gettop(L) == base + 4); // TODO: REMOVE
// Search among bases
int original_metatable = base+4;
assert(lua_gettop(L) == original_metatable); // Check that stack is correct
SWIG_Lua_get_table(L,".bases");
assert(lua_istable(L,-1));
int bases_count = lua_rawlen(L,-1);
if(bases_count>0)
{
int i = 0;
int ret = 0;
lua_pushvalue(L,base+1); // push userdata
lua_pushvalue(L,base+2); // Push key again
lua_pushvalue(L,base+3); // Push value again
// Trick: temporaly replacing original metatable
// with metatable for base class and call getter
for(i=0;i<bases_count;i++) {
lua_rawgeti(L,-4,i+1); // get base metatable here
assert(lua_istable(L,-1));
assert(lua_isuserdata(L,-4));
lua_setmetatable(L,-4); // Set new metatable
assert(lua_isuserdata(L,-3));
ret = SWIG_Lua_class_do_set(L); // Forward call
assert(ret==0||ret==-1);
if(ret==0)
break;
}
// Return original metatable back
lua_pushvalue(L,original_metatable);
lua_setmetatable(L,base+1);
if(ret==0)
{
// tidy stack. Stack currently is:
// --base--
// userdata
// key
// value
// metatable
// .bases table
// userdata
// key : -2
// value: -1
lua_pop(L,5);
return 0;
} else {
lua_pop(L,3); // remove userdata, key and value
}
}
lua_pop(L,1); // remove .bases_table
lua_pop(L,1); // remove metatable
assert(lua_gettop(L) == base+3);
return -1; // Indicator that search failed
}
/* This is actuall method exported to Lua. It calls SWIG_Lua_class_do_set and correctly
* handlers return value
*/
SWIGINTERN int SWIG_Lua_class_set(lua_State* L)
{
int ret= SWIG_Lua_class_do_set(L);
if(ret==0)
return 0;
else if(ret==-1) {
SWIG_Lua_pushferrstring(L,"Assignment not possible. No setter/member with this name. For custom assignments implement __setitem method");
lua_error(L);
} else {
assert(0); // Internal implementation error
return 0;
} }
return 0;
} }
/* the class.destruct method called by the interpreter */ /* the class.destruct method called by the interpreter */
@ -752,23 +903,6 @@ SWIGINTERN int SWIG_Lua_class_disown(lua_State* L)
return 0; return 0;
} }
/* Constructor proxy. Used when class name entry in module is not class constructor,
but special table instead. */
SWIGINTERN int SWIG_Lua_constructor_proxy(lua_State* L)
{
/* unlimited number of parameters
First one is our proxy table and we should remove it
Other we should pass to real constructor
*/
assert(lua_istable(L,1));
lua_pushstring(L,".constructor");
lua_rawget(L,1);
assert(!lua_isnil(L,-1));
lua_replace(L,1); /* replace our table with real constructor */
lua_call(L,lua_gettop(L)-1,1);
return 1;
}
/* gets the swig class registry (or creates it) */ /* gets the swig class registry (or creates it) */
SWIGINTERN void SWIG_Lua_get_class_registry(lua_State* L) SWIGINTERN void SWIG_Lua_get_class_registry(lua_State* L)
{ {
@ -829,15 +963,24 @@ SWIGINTERN void SWIG_Lua_add_class_static_details(lua_State* L, swig_lua_class*
} }
/* helper to recursively add class details (attributes & operations) */ /* helper to recursively add class details (attributes & operations) */
SWIGINTERN void SWIG_Lua_add_class_details(lua_State* L,swig_lua_class* clss) SWIGINTERN void SWIG_Lua_add_class_instance_details(lua_State* L,swig_lua_class* clss)
{ {
int i; int i;
/* call all the base classes first: we can then override these later: */ // Add bases to .bases table
SWIG_Lua_get_table(L,".bases");
assert(lua_istable(L,-1)); /* just in case */
int bases_count = 0;
for(i=0;clss->bases[i];i++) for(i=0;clss->bases[i];i++)
{ {
SWIG_Lua_add_class_details(L,clss->bases[i]); SWIG_Lua_get_class_metatable(L,clss->bases[i]->fqname);
// Base class must be already registered
assert(lua_istable(L,-1));
lua_rawseti(L,-2,i+1); // In lua indexing starts from 1
bases_count++;
} }
/* add fns */ assert(lua_rawlen(L,-1) == bases_count);
lua_pop(L,1); // remove .bases table
/* add attributes */
for(i=0;clss->attributes[i].name;i++){ for(i=0;clss->attributes[i].name;i++){
SWIG_Lua_add_variable(L,clss->attributes[i].name,clss->attributes[i].getmethod,clss->attributes[i].setmethod); SWIG_Lua_add_variable(L,clss->attributes[i].name,clss->attributes[i].getmethod,clss->attributes[i].setmethod);
} }
@ -851,7 +994,7 @@ SWIGINTERN void SWIG_Lua_add_class_details(lua_State* L,swig_lua_class* clss)
/* add operator overloads /* add operator overloads
these look ANY method which start with "__" and assume they these look ANY method which start with "__" and assume they
are operator overloads & add them to the metatable are operator overloads & add them to the metatable
(this might mess up is someone defines a method __gc (the destructor)*/ (this might mess up if someone defines a method __gc (the destructor)*/
for(i=0;clss->methods[i].name;i++){ for(i=0;clss->methods[i].name;i++){
if (clss->methods[i].name[0]=='_' && clss->methods[i].name[1]=='_'){ if (clss->methods[i].name[0]=='_' && clss->methods[i].name[1]=='_'){
SWIG_Lua_add_function(L,clss->methods[i].name,clss->methods[i].func); SWIG_Lua_add_function(L,clss->methods[i].name,clss->methods[i].func);
@ -884,13 +1027,13 @@ SWIGINTERN void SWIG_Lua_init_base_class(lua_State* L,swig_lua_class* clss)
/* Register class static methods,attributes etc as well as constructor proxy */ /* Register class static methods,attributes etc as well as constructor proxy */
SWIGINTERN void SWIG_Lua_class_register_static(lua_State* L, swig_lua_class* clss) SWIGINTERN void SWIG_Lua_class_register_static(lua_State* L, swig_lua_class* clss)
{ {
int begin = lua_gettop(L);
lua_checkstack(L,5); /* just in case */ lua_checkstack(L,5); /* just in case */
assert(lua_istable(L,-1)); /* just in case */ assert(lua_istable(L,-1)); /* just in case */
assert(strcmp(clss->name, clss->cls_static.name) == 0); /* in class those 2 must be equal */ assert(strcmp(clss->name, clss->cls_static.name) == 0); /* in class those 2 must be equal */
SWIG_Lua_namespace_register(L,&clss->cls_static, false); SWIG_Lua_namespace_register(L,&clss->cls_static, true);
SWIG_Lua_get_table(L,clss->name); // Get namespace table back
assert(lua_istable(L,-1)); /* just in case */ assert(lua_istable(L,-1)); /* just in case */
/* add its constructor to module with the name of the class /* add its constructor to module with the name of the class
@ -899,10 +1042,9 @@ SWIGINTERN void SWIG_Lua_class_register_static(lua_State* L, swig_lua_class* cls
(this overcomes the problem of pure virtual classes without constructors)*/ (this overcomes the problem of pure virtual classes without constructors)*/
if (clss->constructor) if (clss->constructor)
{ {
SWIG_Lua_add_function(L,".constructor", clss->constructor);
lua_getmetatable(L,-1); lua_getmetatable(L,-1);
assert(lua_istable(L,-1)); /* just in case */ assert(lua_istable(L,-1)); /* just in case */
SWIG_Lua_add_function(L,"__call", SWIG_Lua_constructor_proxy); SWIG_Lua_add_function(L,"__call", clss->constructor);
lua_pop(L,1); lua_pop(L,1);
} }
@ -911,19 +1053,42 @@ SWIGINTERN void SWIG_Lua_class_register_static(lua_State* L, swig_lua_class* cls
/* clear stack */ /* clear stack */
lua_pop(L,1); lua_pop(L,1);
assert( lua_gettop(L) == begin );
} }
/* performs the entire class registration process */ /* performs the instance(non-static) class registration process. Metatable for class is created
SWIGINTERN void SWIG_Lua_class_register(lua_State* L,swig_lua_class* clss) * and added to the class registry.
*/
SWIGINTERN void SWIG_Lua_class_register_instance(lua_State* L,swig_lua_class* clss)
{ {
SWIG_Lua_class_register_static(L,clss); int begin = lua_gettop(L);
// if name already there (class is already registered) then do nothing
SWIG_Lua_get_class_registry(L); /* get the registry */ SWIG_Lua_get_class_registry(L); /* get the registry */
lua_pushstring(L,clss->name); /* get the name */ lua_pushstring(L,clss->fqname); /* get the name */
lua_rawget(L,-2);
if(!lua_isnil(L,-1)) {
lua_pop(L,2);
assert(lua_gettop(L)==begin);
return;
}
lua_pop(L,2); // tidy stack
// Recursively initialize all bases
int i = 0;
for(i=0;clss->bases[i];i++)
{
SWIG_Lua_class_register_instance(L,clss->bases[i]);
}
// Again, get registry and push name
SWIG_Lua_get_class_registry(L); /* get the registry */
lua_pushstring(L,clss->fqname); /* get the name */
lua_newtable(L); /* create the metatable */ lua_newtable(L); /* create the metatable */
/* add string of class name called ".type" */ /* add string of class name called ".type" */
lua_pushstring(L,".type"); lua_pushstring(L,".type");
lua_pushstring(L,clss->name); lua_pushstring(L,clss->fqname);
lua_rawset(L,-3);
/* add a table called bases */
lua_pushstring(L,".bases");
lua_newtable(L);
lua_rawset(L,-3); lua_rawset(L,-3);
/* add a table called ".get" */ /* add a table called ".get" */
lua_pushstring(L,".get"); lua_pushstring(L,".get");
@ -948,10 +1113,18 @@ SWIGINTERN void SWIG_Lua_class_register(lua_State* L,swig_lua_class* clss)
/* add it */ /* add it */
lua_rawset(L,-3); /* metatable into registry */ lua_rawset(L,-3); /* metatable into registry */
lua_pop(L,1); /* tidy stack (remove registry) */ lua_pop(L,1); /* tidy stack (remove registry) */
assert(lua_gettop(L)==begin);
SWIG_Lua_get_class_metatable(L,clss->name); SWIG_Lua_get_class_metatable(L,clss->fqname);
SWIG_Lua_add_class_details(L,clss); /* recursive adding of details (atts & ops) */ SWIG_Lua_add_class_instance_details(L,clss); /* recursive adding of details (atts & ops) */
lua_pop(L,1); /* tidy stack (remove class metatable) */ lua_pop(L,1); /* tidy stack (remove class metatable) */
assert( lua_gettop(L) == begin );
}
SWIGINTERN void SWIG_Lua_class_register(lua_State* L,swig_lua_class* clss)
{
SWIG_Lua_class_register_instance(L,clss);
SWIG_Lua_class_register_static(L,clss);
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
@ -963,7 +1136,7 @@ SWIGINTERN void _SWIG_Lua_AddMetatable(lua_State* L,swig_type_info *type)
{ {
if (type->clientdata) /* there is clientdata: so add the metatable */ if (type->clientdata) /* there is clientdata: so add the metatable */
{ {
SWIG_Lua_get_class_metatable(L,((swig_lua_class*)(type->clientdata))->name); SWIG_Lua_get_class_metatable(L,((swig_lua_class*)(type->clientdata))->fqname);
if (lua_istable(L,-1)) if (lua_istable(L,-1))
{ {
lua_setmetatable(L,-2); lua_setmetatable(L,-2);

View file

@ -1490,6 +1490,7 @@ int Language::membervariableHandler(Node *n) {
Setattr(n, "type", type); Setattr(n, "type", type);
Setattr(n, "name", name); Setattr(n, "name", name);
Setattr(n, "sym:name", symname); Setattr(n, "sym:name", symname);
Delattr(n, "memberset");
/* Delete all attached typemaps and typemap attributes */ /* Delete all attached typemaps and typemap attributes */
Iterator ki; Iterator ki;
@ -1507,6 +1508,7 @@ int Language::membervariableHandler(Node *n) {
Setattr(n, "sym:name", mrename_get); Setattr(n, "sym:name", mrename_get);
Setattr(n, "memberget", "1"); Setattr(n, "memberget", "1");
functionWrapper(n); functionWrapper(n);
Delattr(n, "memberget");
} }
Delete(mrename_get); Delete(mrename_get);
Delete(mrename_set); Delete(mrename_set);
@ -2951,11 +2953,14 @@ int Language::constantWrapper(Node *n) {
* ---------------------------------------------------------------------- */ * ---------------------------------------------------------------------- */
int Language::variableWrapper(Node *n) { int Language::variableWrapper(Node *n) {
Swig_require("variableWrapper", n, "*name", "*sym:name", "*type", "?parms", NIL); Swig_require("variableWrapper", n, "*name", "*sym:name", "*type", "?parms", "?varset", "?varget", NIL);
String *symname = Getattr(n, "sym:name"); String *symname = Getattr(n, "sym:name");
SwigType *type = Getattr(n, "type"); SwigType *type = Getattr(n, "type");
String *name = Getattr(n, "name"); String *name = Getattr(n, "name");
Delattr(n,"varset");
Delattr(n,"varget");
/* If no way to set variables. We simply create functions */ /* If no way to set variables. We simply create functions */
int assignable = is_assignable(n); int assignable = is_assignable(n);
int flags = use_naturalvar_mode(n); int flags = use_naturalvar_mode(n);
@ -2986,12 +2991,14 @@ int Language::variableWrapper(Node *n) {
Delete(pname0); Delete(pname0);
} }
if (make_set_wrapper) { if (make_set_wrapper) {
Setattr(n, "varset", "1");
functionWrapper(n); functionWrapper(n);
} }
/* Restore parameters */ /* Restore parameters */
Setattr(n, "sym:name", symname); Setattr(n, "sym:name", symname);
Setattr(n, "type", type); Setattr(n, "type", type);
Setattr(n, "name", name); Setattr(n, "name", name);
Delattr(n, "varset");
/* Delete all attached typemaps and typemap attributes */ /* Delete all attached typemaps and typemap attributes */
Iterator ki; Iterator ki;
@ -3005,6 +3012,7 @@ int Language::variableWrapper(Node *n) {
String *gname = Swig_name_get(NSpace, symname); String *gname = Swig_name_get(NSpace, symname);
Setattr(n, "sym:name", gname); Setattr(n, "sym:name", gname);
Delete(gname); Delete(gname);
Setattr(n, "varget", "1");
functionWrapper(n); functionWrapper(n);
Swig_restore(n); Swig_restore(n);
return SWIG_OK; return SWIG_OK;

View file

@ -122,13 +122,20 @@ private:
//String *s_vars_meta_tab; // metatable for variables //String *s_vars_meta_tab; // metatable for variables
Hash* namespaces_hash; Hash* namespaces_hash;
// Parameters for current class. NIL if not parsing class
int have_constructor; int have_constructor;
int have_destructor; int have_destructor;
String *destructor_action; String *destructor_action;
String *class_symname; String *class_symname;
String *class_fq_symname; // Fully qualified symname - NSpace + '.' + class_symname
String *class_static_nspace;
String *constructor_name; String *constructor_name;
enum { // Many wrappers forward calls to each other, for example staticmembervariableHandler
// forwards call to variableHandler, which, in turn, makes to call to functionWrapper.
// In order to access information about whether it is static member of class or just
// plain old variable an array current is kept and used as 'log' of call stack.
enum TState {
NO_CPP, NO_CPP,
VARIABLE, VARIABLE,
MEMBER_FUNC, MEMBER_FUNC,
@ -137,8 +144,12 @@ private:
MEMBER_VAR, MEMBER_VAR,
CLASS_CONST, CLASS_CONST,
STATIC_FUNC, STATIC_FUNC,
STATIC_VAR STATIC_VAR,
}current; STATIC_CONST, // enums and things like static const int x = 5;
STATES_COUNT
};
bool current[STATES_COUNT];
public: public:
@ -175,10 +186,14 @@ public:
have_destructor(0), have_destructor(0),
destructor_action(0), destructor_action(0),
class_symname(0), class_symname(0),
constructor_name(0), class_fq_symname(0),
current(NO_CPP) { class_static_nspace(0),
constructor_name(0) {
namespaces_hash = NewHash(); namespaces_hash = NewHash();
for(int i = 0; i < STATES_COUNT; i++ )
current[i] = false;
} }
~LUA() { ~LUA() {
if(namespaces_hash) if(namespaces_hash)
Delete(namespaces_hash); Delete(namespaces_hash);
@ -306,7 +321,9 @@ public:
s_luacode = NewString(""); s_luacode = NewString("");
Swig_register_filebyname("luacode", s_luacode); Swig_register_filebyname("luacode", s_luacode);
current=NO_CPP; current[NO_CPP] = true;
// Registering names schemes
Swig_name_register("member", "%m");
/* Standard stuff for the SWIG runtime section */ /* Standard stuff for the SWIG runtime section */
Swig_banner(f_begin); Swig_banner(f_begin);
@ -473,6 +490,21 @@ public:
* Create a function declaration and register it with the interpreter. * Create a function declaration and register it with the interpreter.
* --------------------------------------------------------------------- */ * --------------------------------------------------------------------- */
// Helper function. Remembers wrap name
void rememberWrapName(Node *n, String *wrapname) {
Setattr(n, "wrap:name", wrapname);
// If it is getter/setter, then write wrapname under
// wrap:memberset/wrap:memberget accordingly
if( Getattr(n, "memberset") )
Setattr(n, "memberset:wrap:name", wrapname);
if( Getattr(n, "varset") )
Setattr(n, "varset:wrap:name", wrapname);
if( Getattr(n, "memberget") )
Setattr(n, "memberget:wrap:name", wrapname);
if( Getattr(n, "varget") )
Setattr(n, "varget:wrap:name", wrapname);
}
virtual int functionWrapper(Node *n) { virtual int functionWrapper(Node *n) {
REPORT("functionWrapper",n); REPORT("functionWrapper",n);
@ -491,7 +523,7 @@ public:
if (Getattr(n, "sym:overloaded")) { if (Getattr(n, "sym:overloaded")) {
overname = Getattr(n, "sym:overname"); overname = Getattr(n, "sym:overname");
} else { } else {
if (!addSymbol(iname, n, getNSpace())) { if (!luaAddSymbol(iname, n)) {
Printf(stderr,"addSymbol(%s) failed\n",iname); Printf(stderr,"addSymbol(%s) failed\n",iname);
return SWIG_ERROR; return SWIG_ERROR;
} }
@ -505,11 +537,13 @@ public:
Wrapper_add_local(f, "SWIG_arg", "int SWIG_arg = 0"); Wrapper_add_local(f, "SWIG_arg", "int SWIG_arg = 0");
String *wname = Swig_name_wrapper(iname); String* fqname = fully_qualified_name(iname);
String *wname = Swig_name_wrapper(fqname);
Delete(fqname);
if (overname) { if (overname) {
Append(wname, overname); Append(wname, overname);
} }
if (current == CONSTRUCTOR) { if (current[CONSTRUCTOR]) {
if( constructor_name != 0) if( constructor_name != 0)
Delete(constructor_name); Delete(constructor_name);
constructor_name = Copy(wname); constructor_name = Copy(wname);
@ -552,12 +586,6 @@ public:
} }
/* Which input argument to start with? */
// int start = (current == MEMBER_FUNC || current == MEMBER_VAR || current == DESTRUCTOR) ? 1 : 0;
/* Offset to skip over the attribute name */
// int offset = (current == MEMBER_VAR) ? 1 : 0;
/* NEW LANGUAGE NOTE:*********************************************** /* NEW LANGUAGE NOTE:***********************************************
from here on in, it gets rather hairy from here on in, it gets rather hairy
this is the code to convert from the scripting language to C/C++ this is the code to convert from the scripting language to C/C++
@ -693,14 +721,7 @@ public:
} }
// Remember C name of the wrapping function // Remember C name of the wrapping function
Setattr(n, "wrap:name", wname); rememberWrapName(n, wname);
// If it is getter/setter, then write wname under
// wrap:memberset/wrap:memberget accordingly
if( Getattr(n, "memberset") )
Setattr(n, "memberset:wrap:name", wname);
if( Getattr(n, "memberget") )
Setattr(n, "memberget:wrap:name", wname);
/* Emit the function call */ /* Emit the function call */
String *actioncode = emit_action(n); String *actioncode = emit_action(n);
@ -777,7 +798,7 @@ public:
Therefore we go though the whole function, Therefore we go though the whole function,
but do not write the code into the wrapper but do not write the code into the wrapper
*/ */
if(current!=DESTRUCTOR) { if(!current[DESTRUCTOR]) {
Wrapper_print(f, f_wrappers); Wrapper_print(f, f_wrappers);
} }
@ -789,7 +810,7 @@ public:
if (!Getattr(n, "sym:overloaded")) { if (!Getattr(n, "sym:overloaded")) {
//REPORT("dispatchFunction", n); //REPORT("dispatchFunction", n);
// add_method(n, iname, wname, description); // add_method(n, iname, wname, description);
if (current==NO_CPP || current==STATIC_FUNC) { // emit normal fns & static fns if (current[NO_CPP] || current[STATIC_FUNC]) { // emit normal fns & static fns
Hash* nspaceHash = getNamespaceHash( getNSpace() ); Hash* nspaceHash = getNamespaceHash( getNSpace() );
String* s_ns_methods_tab = Getattr(nspaceHash, "methods"); String* s_ns_methods_tab = Getattr(nspaceHash, "methods");
if(elua_ltr || eluac_ltr) if(elua_ltr || eluac_ltr)
@ -877,24 +898,19 @@ public:
Printv(f->code, "}\n", NIL); Printv(f->code, "}\n", NIL);
Wrapper_print(f, f_wrappers); Wrapper_print(f, f_wrappers);
//add_method(symname,wname,0); //add_method(symname,wname,0);
if (current==NO_CPP || current==STATIC_FUNC) { // emit normal fns & static fns if (current[NO_CPP] || current[STATIC_FUNC]) { // emit normal fns & static fns
Hash* nspaceHash = getNamespaceHash( getNSpace() ); Hash* nspaceHash = getNamespaceHash( getNSpace() );
String* s_ns_methods_tab = Getattr(nspaceHash, "methods"); String* s_ns_methods_tab = Getattr(nspaceHash, "methods");
Printv(s_ns_methods_tab, tab4, "{ \"", symname, "\",", wname, "},\n", NIL); Printv(s_ns_methods_tab, tab4, "{ \"", symname, "\",", wname, "},\n", NIL);
} }
if (current == CONSTRUCTOR) { if (current[CONSTRUCTOR]) {
if( constructor_name != 0 ) if( constructor_name != 0 )
Delete(constructor_name); Delete(constructor_name);
constructor_name = Copy(wname); constructor_name = Copy(wname);
} }
Setattr(n, "wrap:name", wname); // Remember C name of the wrapping function
// If it is getter/setter, then write wname under rememberWrapName(n, wname);
// wrap:memberset/wrap:memberget accordingly
if( Getattr(n, "memberset") )
Setattr(n, "memberset:wrap:name", wname);
if( Getattr(n, "memberget") )
Setattr(n, "memberget:wrap:name", wname);
DelWrapper(f); DelWrapper(f);
Delete(dispatch); Delete(dispatch);
@ -916,13 +932,14 @@ public:
NEW LANGUAGE NOTE:END ************************************************/ NEW LANGUAGE NOTE:END ************************************************/
// REPORT("variableWrapper", n); // REPORT("variableWrapper", n);
String *iname = Getattr(n, "sym:name"); String *iname = Getattr(n, "sym:name");
current=VARIABLE; String *unassignable = NewString("SWIG_Lua_set_immutable");
current[VARIABLE] = true;
// let SWIG generate the wrappers // let SWIG generate the wrappers
int result = Language::variableWrapper(n); int result = Language::variableWrapper(n);
current=NO_CPP; current[VARIABLE] = false;
// normally SWIG will generate 2 wrappers, a get and a set // normally SWIG will generate 2 wrappers, a get and a set
// but in certain scenarios (immutable, or if its arrays), it will not // but in certain scenarios (immutable, or if its arrays), it will not
String *getName = Swig_name_wrapper(Swig_name_get(getNSpace(), iname)); String *getName = Getattr(n,"varget:wrap:name");
String *setName = 0; String *setName = 0;
// checking whether it can be set to or not appears to be a very error prone issue // checking whether it can be set to or not appears to be a very error prone issue
// I referred to the Language::variableWrapper() to find this out // I referred to the Language::variableWrapper() to find this out
@ -934,14 +951,15 @@ public:
Delete(tm); Delete(tm);
if (assignable) { if (assignable) {
setName = Swig_name_wrapper(Swig_name_set(getNSpace(), iname)); setName = Getattr(n,"varset:wrap:name");
} else { } else {
// how about calling a 'this is not settable' error message? // how about calling a 'this is not settable' error message?
setName = NewString("SWIG_Lua_set_immutable"); // error message setName = unassignable;// error message
//setName = NewString("0");
} }
// register the variable // register the variable
assert(setName != 0);
assert(getName != 0);
Hash* nspaceHash = getNamespaceHash( getNSpace() ); Hash* nspaceHash = getNamespaceHash( getNSpace() );
String* s_ns_methods_tab = Getattr(nspaceHash, "methods"); String* s_ns_methods_tab = Getattr(nspaceHash, "methods");
String* s_ns_var_tab = Getattr(nspaceHash, "attributes"); String* s_ns_var_tab = Getattr(nspaceHash, "attributes");
@ -956,12 +974,11 @@ public:
} else { } else {
Printf(s_ns_var_tab, "%s{ \"%s\", %s, %s },\n", tab4, iname, getName, setName); Printf(s_ns_var_tab, "%s{ \"%s\", %s, %s },\n", tab4, iname, getName, setName);
} }
if (getCurrentClass()) { if (getCurrentClass()) { // TODO: REMOVE
Setattr(n, "luaclassobj:wrap:get", getName); Setattr(n, "luaclassobj:wrap:get", getName);
Setattr(n, "luaclassobj:wrap:set", setName); Setattr(n, "luaclassobj:wrap:set", setName);
} else { } else {
Delete(getName); Delete(unassignable);
Delete(setName);
} }
return result; return result;
} }
@ -978,8 +995,9 @@ public:
String *rawval = Getattr(n, "rawval"); String *rawval = Getattr(n, "rawval");
String *value = rawval ? rawval : Getattr(n, "value"); String *value = rawval ? rawval : Getattr(n, "value");
String *tm; String *tm;
//Printf( stdout, "Add constant %s, ns %s\n", iname, getNSpace() );// TODO: REMOVE
if (!addSymbol(iname, n, getNSpace())) if (!luaAddSymbol(iname, n))
return SWIG_ERROR; return SWIG_ERROR;
/* Special hook for member pointer */ /* Special hook for member pointer */
@ -1035,7 +1053,7 @@ public:
// REPORT("nativeWrapper", n); // REPORT("nativeWrapper", n);
String *symname = Getattr(n, "sym:name"); String *symname = Getattr(n, "sym:name");
String *wrapname = Getattr(n, "wrap:name"); String *wrapname = Getattr(n, "wrap:name");
if (!addSymbol(wrapname, n, getNSpace())) if (!luaAddSymbol(wrapname, n))
return SWIG_ERROR; return SWIG_ERROR;
Hash *nspaceHash = getNamespaceHash( getNSpace() ); Hash *nspaceHash = getNamespaceHash( getNSpace() );
@ -1050,7 +1068,23 @@ public:
* ------------------------------------------------------------ */ * ------------------------------------------------------------ */
virtual int enumDeclaration(Node *n) { virtual int enumDeclaration(Node *n) {
return Language::enumDeclaration(n); // enumDeclaration supplied by Language is messing with NSpace.
// So this is the exact copy of function from Language with
// correct handling of namespaces
String *oldNSpace = getNSpace();
if( getCurrentClass() == 0 ) {
setNSpace(Getattr(n, "sym:nspace"));
}
if (!ImportMode) {
current[STATIC_CONST] = true;
emit_children(n);
current[STATIC_CONST] = false;
}
setNSpace(oldNSpace);
return SWIG_OK;
} }
/* ------------------------------------------------------------ /* ------------------------------------------------------------
@ -1058,7 +1092,27 @@ public:
* ------------------------------------------------------------ */ * ------------------------------------------------------------ */
virtual int enumvalueDeclaration(Node *n) { virtual int enumvalueDeclaration(Node *n) {
return Language::enumvalueDeclaration(n); if (getCurrentClass() && (cplus_mode != PUBLIC))
return SWIG_NOWRAP;
Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
String *value = Getattr(n, "value");
String *name = Getattr(n, "name");
String *tmpValue;
if (value)
tmpValue = NewString(value);
else
tmpValue = NewString(name);
Setattr(n, "value", tmpValue);
Setattr(n, "name", tmpValue); /* for wrapping of enums in a namespace when emit_action is used */
constantWrapper(n);
Delete(tmpValue);
Swig_restore(n);
// TODO: Backward compatibility: add ClassName_ConstantName member
return SWIG_OK;
} }
/* ------------------------------------------------------------ /* ------------------------------------------------------------
@ -1076,8 +1130,7 @@ public:
virtual int classHandler(Node *n) { virtual int classHandler(Node *n) {
//REPORT("classHandler", n); //REPORT("classHandler", n);
String *mangled_full_class_symname = 0; String *mangled_class_fq_symname = 0;
String *full_class_symname = 0;
String* nspace = getNSpace(); String* nspace = getNSpace();
String* destructor_name = 0; String* destructor_name = 0;
@ -1085,19 +1138,27 @@ public:
have_constructor = 0; have_constructor = 0;
have_destructor = 0; have_destructor = 0;
destructor_action = 0; destructor_action = 0;
assert(class_static_nspace == 0);
assert(class_fq_symname == 0);
assert(class_symname == 0);
current[NO_CPP] = false;
class_symname = Getattr(n, "sym:name"); class_symname = Getattr(n, "sym:name");
if (!addSymbol(class_symname, n, nspace)) // We have to enforce nspace here, because technically we are already
// inside class parsing (getCurrentClass != 0), but we should register
// class in the it's parent namespace
if (!luaAddSymbol(class_symname, n, nspace))
return SWIG_ERROR; return SWIG_ERROR;
if (nspace == 0) if (nspace == 0)
full_class_symname = NewStringf("%s", class_symname); class_fq_symname = NewStringf("%s", class_symname);
else else
full_class_symname = NewStringf("%s.%s", nspace, class_symname); class_fq_symname = NewStringf("%s.%s", nspace, class_symname);
assert(full_class_symname != 0); assert(class_fq_symname != 0);
mangled_full_class_symname = Swig_name_mangle(full_class_symname); mangled_class_fq_symname = Swig_name_mangle(class_fq_symname);
Printf( stdout, "Mangled class symname %s\n", mangled_full_class_symname ); Printf( stdout, "Mangled class symname %s\n", mangled_class_fq_symname );
// not sure exactly how this works, // not sure exactly how this works,
// but tcl has a static hashtable of all classes emitted and then only emits code for them once. // but tcl has a static hashtable of all classes emitted and then only emits code for them once.
@ -1107,9 +1168,9 @@ public:
// * consider effect on template_specialization_defarg // * consider effect on template_specialization_defarg
static Hash *emitted = NewHash(); static Hash *emitted = NewHash();
if (Getattr(emitted, mangled_full_class_symname)) if (Getattr(emitted, mangled_class_fq_symname))
return SWIG_NOWRAP; return SWIG_NOWRAP;
Setattr(emitted, mangled_full_class_symname, "1"); Setattr(emitted, mangled_class_fq_symname, "1");
// We treat class T as both 'class' and 'namespace'. All static members, attributes // We treat class T as both 'class' and 'namespace'. All static members, attributes
// and constants are considered part of namespace T, all members - part of the 'class' // and constants are considered part of namespace T, all members - part of the 'class'
@ -1122,7 +1183,7 @@ public:
// And we can guarantee that there will not be any name collision because names starting with 2 underscores // And we can guarantee that there will not be any name collision because names starting with 2 underscores
// and capital letter are forbiden to use in C++. So, under know circumstances could our class contain // and capital letter are forbiden to use in C++. So, under know circumstances could our class contain
// any member or subclass with name "__Static". Thus, never any name clash. // any member or subclass with name "__Static". Thus, never any name clash.
Hash* non_static_cls = getNamespaceHash(full_class_symname, false); Hash* non_static_cls = getNamespaceHash(class_fq_symname, false);
assert(non_static_cls != 0); assert(non_static_cls != 0);
s_attr_tab = Getattr(non_static_cls, "attributes"); s_attr_tab = Getattr(non_static_cls, "attributes");
s_methods_tab = Getattr(non_static_cls, "methods"); s_methods_tab = Getattr(non_static_cls, "methods");
@ -1135,11 +1196,9 @@ public:
* All constants are considered part of static part of class. * All constants are considered part of static part of class.
*/ */
String *static_cls_key = NewStringf("%s%s__Static", full_class_symname, NSPACE_SEPARATOR); class_static_nspace = NewStringf("%s%s__Static", class_fq_symname, NSPACE_SEPARATOR);
Hash *static_cls = getNamespaceHash(static_cls_key, false); Hash *static_cls = getNamespaceHash(class_static_nspace, false);
if (static_cls == 0) { assert(static_cls != 0);
return SWIG_ERROR; // This cant be, so it is internal, implementation error
}
Setattr(static_cls, "lua:no_namespaces", "1"); Setattr(static_cls, "lua:no_namespaces", "1");
/* TODO: REMOVE /* TODO: REMOVE
s_cls_methods_tab = Getattr(static_cls, "methods"); s_cls_methods_tab = Getattr(static_cls, "methods");
@ -1160,17 +1219,18 @@ public:
// Replacing namespace with namespace + class in order to static // Replacing namespace with namespace + class in order to static
// member be put inside class static area // member be put inside class static area
setNSpace(static_cls_key); setNSpace(class_static_nspace);
// Generate normal wrappers // Generate normal wrappers
Language::classHandler(n); Language::classHandler(n);
// Restore correct nspace // Restore correct nspace
setNSpace(nspace); setNSpace(nspace);
//Printf( stdout, "Class finished\n" ); TODO:REMOVE
SwigType *t = Copy(Getattr(n, "name")); SwigType *t = Copy(Getattr(n, "name"));
SwigType_add_pointer(t); SwigType_add_pointer(t);
// Catch all: eg. a class with only static functions and/or variables will not have 'remembered' // Catch all: eg. a class with only static functions and/or variables will not have 'remembered'
String *wrap_class = NewStringf("&_wrap_class_%s", mangled_full_class_symname); String *wrap_class = NewStringf("&_wrap_class_%s", mangled_class_fq_symname);
SwigType_remember_clientdata(t, wrap_class); SwigType_remember_clientdata(t, wrap_class);
String *rt = Copy(getClassType()); String *rt = Copy(getClassType());
@ -1182,12 +1242,12 @@ public:
Printv( ns_classes, wrap_class, ",\n", NIL ); Printv( ns_classes, wrap_class, ",\n", NIL );
// Register the class structure with the type checker // Register the class structure with the type checker
// Printf(f_init,"SWIG_TypeClientData(SWIGTYPE%s, (void *) &_wrap_class_%s);\n", SwigType_manglestr(t), mangled_full_class_symname); // Printf(f_init,"SWIG_TypeClientData(SWIGTYPE%s, (void *) &_wrap_class_%s);\n", SwigType_manglestr(t), mangled_class_fq_symname);
// emit a function to be called to delete the object // emit a function to be called to delete the object
// TODO: class_name -> full_class_name || mangled full_class_name // TODO: class_name -> full_class_name || mangled full_class_name
if (have_destructor) { if (have_destructor) {
destructor_name = NewStringf("swig_delete_%s", mangled_full_class_symname); destructor_name = NewStringf("swig_delete_%s", mangled_class_fq_symname);
Printv(f_wrappers, "static void ", destructor_name, "(void *obj) {\n", NIL); Printv(f_wrappers, "static void ", destructor_name, "(void *obj) {\n", NIL);
if (destructor_action) { if (destructor_action) {
Printv(f_wrappers, SwigType_str(rt, "arg1"), " = (", SwigType_str(rt, 0), ") obj;\n", NIL); Printv(f_wrappers, SwigType_str(rt, "arg1"), " = (", SwigType_str(rt, 0), ") obj;\n", NIL);
@ -1201,9 +1261,26 @@ public:
} }
Printf(f_wrappers, "}\n"); Printf(f_wrappers, "}\n");
} }
// Wrap constructor wrapper into one more proxy function. It will be used as class namespace __call method, thus
// allowing both
// Module.ClassName.StaticMethod to access static method/variable/constant
// Module.ClassName() to create new object
if (have_constructor) {
String* constructor_proxy_name = NewStringf("_proxy_%s", constructor_name);
Printv(f_wrappers, "static int ", constructor_proxy_name, "(lua_State *L) {\n", NIL);
Printv(f_wrappers,
tab4, "assert(lua_istable(L,1));\n",
tab4, "lua_pushcfunction(L,", constructor_name, ");\n",
tab4, "assert(!lua_isnil(L,-1));\n",
tab4, "lua_replace(L,1); /* replace our table with real constructor */\n",
tab4, "lua_call(L,lua_gettop(L)-1,1);\n",
tab4, "return 1;\n}\n", NIL);
Delete(constructor_name);
constructor_name = constructor_proxy_name;
}
closeNamespaceHash(full_class_symname, f_wrappers); closeNamespaceHash(class_fq_symname, f_wrappers);
closeNamespaceHash(static_cls_key, f_wrappers); closeNamespaceHash(class_static_nspace, f_wrappers);
/* TODO: REMOVE /* TODO: REMOVE
@ -1251,12 +1328,12 @@ public:
} }
} }
Printv(f_wrappers, "static swig_lua_class *swig_", mangled_full_class_symname, "_bases[] = {", base_class, "0};\n", NIL); Printv(f_wrappers, "static swig_lua_class *swig_", mangled_class_fq_symname, "_bases[] = {", base_class, "0};\n", NIL);
Delete(base_class); Delete(base_class);
Printv(f_wrappers, "static const char *swig_", mangled_full_class_symname, "_base_names[] = {", base_class_names, "0};\n", NIL); Printv(f_wrappers, "static const char *swig_", mangled_class_fq_symname, "_base_names[] = {", base_class_names, "0};\n", NIL);
Delete(base_class_names); Delete(base_class_names);
Printv(f_wrappers, "static swig_lua_class _wrap_class_", mangled_full_class_symname, " = { \"", class_symname, "\", &SWIGTYPE", SwigType_manglestr(t), ",", NIL); Printv(f_wrappers, "static swig_lua_class _wrap_class_", mangled_class_fq_symname, " = { \"", class_symname, "\", \"", class_fq_symname,"\", &SWIGTYPE", SwigType_manglestr(t), ",", NIL);
// TODO: Replace with constructor_name // TODO: Replace with constructor_name
if (have_constructor) { if (have_constructor) {
@ -1285,7 +1362,7 @@ public:
if (have_destructor) { if (have_destructor) {
if (eluac_ltr) { if (eluac_ltr) {
String* ns_methods_tab = Getattr(nspaceHash, "methods"); String* ns_methods_tab = Getattr(nspaceHash, "methods");
Printv(ns_methods_tab, tab4, "{LSTRKEY(\"", "free_", mangled_full_class_symname, "\")", ", LFUNCVAL(", destructor_name, ")", "},\n", NIL); Printv(ns_methods_tab, tab4, "{LSTRKEY(\"", "free_", mangled_class_fq_symname, "\")", ", LFUNCVAL(", destructor_name, ")", "},\n", NIL);
Printv(f_wrappers, ", ", destructor_name, NIL); Printv(f_wrappers, ", ", destructor_name, NIL);
} else { } else {
Printv(f_wrappers, ", ", destructor_name, NIL); Printv(f_wrappers, ", ", destructor_name, NIL);
@ -1295,15 +1372,21 @@ public:
} }
Printf(f_wrappers, ", %s, %s, ", s_methods_tab_name, s_attr_tab_name ); Printf(f_wrappers, ", %s, %s, ", s_methods_tab_name, s_attr_tab_name );
// TODO: Replace class_symname with class_name // TODO: Replace class_symname with class_name
printNamespaceDefinition(static_cls_key, class_symname, f_wrappers); printNamespaceDefinition(class_static_nspace, class_symname, f_wrappers);
Printf(f_wrappers, ", swig_%s_bases, swig_%s_base_names };\n\n", Printf(f_wrappers, ", swig_%s_bases, swig_%s_base_names };\n\n",
mangled_full_class_symname, mangled_full_class_symname); mangled_class_fq_symname, mangled_class_fq_symname);
// Printv(f_wrappers, ", swig_", mangled_full_class_symname, "_methods, swig_", mangled_full_class_symname, "_attributes, swig_", mangled_full_class_symname, "_bases };\n\n", NIL); // Printv(f_wrappers, ", swig_", mangled_class_fq_symname, "_methods, swig_", mangled_class_fq_symname, "_attributes, swig_", mangled_class_fq_symname, "_bases };\n\n", NIL);
// Printv(s_cmd_tab, tab4, "{ SWIG_prefix \"", class_name, "\", (swig_wrapper_func) SWIG_ObjectConstructor, &_wrap_class_", mangled_full_class_symname, "},\n", NIL); // Printv(s_cmd_tab, tab4, "{ SWIG_prefix \"", class_name, "\", (swig_wrapper_func) SWIG_ObjectConstructor, &_wrap_class_", mangled_class_fq_symname, "},\n", NIL);
current[NO_CPP] = true;
Delete(t); Delete(t);
Delete(mangled_full_class_symname); Delete(mangled_class_fq_symname);
Delete(static_cls_key); Delete(class_static_nspace);
class_static_nspace = 0;
Delete(class_fq_symname);
class_fq_symname = 0;
class_symname = 0;
return SWIG_OK; return SWIG_OK;
} }
@ -1327,9 +1410,9 @@ public:
String *realname, *rname; String *realname, *rname;
current = MEMBER_FUNC; current[MEMBER_FUNC] = true;
Language::memberfunctionHandler(n); Language::memberfunctionHandler(n);
current = NO_CPP; current[MEMBER_FUNC] = false;
realname = iname ? iname : name; realname = iname ? iname : name;
rname = Getattr(n, "wrap:name"); rname = Getattr(n, "wrap:name");
@ -1350,9 +1433,9 @@ public:
String *symname = Getattr(n, "sym:name"); String *symname = Getattr(n, "sym:name");
String *getter_name, *setter_name; String *getter_name, *setter_name;
current = MEMBER_VAR; current[MEMBER_VAR] = true;
Language::membervariableHandler(n); Language::membervariableHandler(n);
current = NO_CPP; current[MEMBER_VAR] = false;
getter_name = Getattr(n, "memberget:wrap:name"); getter_name = Getattr(n, "memberget:wrap:name");
assert(getter_name != 0); assert(getter_name != 0);
if (!GetFlag(n, "feature:immutable")) { if (!GetFlag(n, "feature:immutable")) {
@ -1382,9 +1465,9 @@ public:
virtual int constructorHandler(Node *n) { virtual int constructorHandler(Node *n) {
// REPORT("constructorHandler", n); // REPORT("constructorHandler", n);
current = CONSTRUCTOR; current[CONSTRUCTOR] = true;
Language::constructorHandler(n); Language::constructorHandler(n);
current = NO_CPP; current[CONSTRUCTOR] = false;
//constructor_name = NewString(Getattr(n, "sym:name")); //constructor_name = NewString(Getattr(n, "sym:name"));
have_constructor = 1; have_constructor = 1;
//Printf( stdout, "Constructor %s\n", constructor_name); TODO: REMOVE //Printf( stdout, "Constructor %s\n", constructor_name); TODO: REMOVE
@ -1397,9 +1480,9 @@ public:
virtual int destructorHandler(Node *n) { virtual int destructorHandler(Node *n) {
REPORT("destructorHandler", n); REPORT("destructorHandler", n);
current = DESTRUCTOR; current[DESTRUCTOR] = true;
Language::destructorHandler(n); Language::destructorHandler(n);
current = NO_CPP; current[DESTRUCTOR] = false;
have_destructor = 1; have_destructor = 1;
destructor_action = Getattr(n, "wrap:action"); destructor_action = Getattr(n, "wrap:action");
return SWIG_OK; return SWIG_OK;
@ -1413,28 +1496,28 @@ public:
virtual int staticmemberfunctionHandler(Node *n) { virtual int staticmemberfunctionHandler(Node *n) {
REPORT("staticmemberfunctionHandler", n); REPORT("staticmemberfunctionHandler", n);
current = STATIC_FUNC; current[STATIC_FUNC] = true;
//String *symname = Getattr(n, "sym:name"); //String *symname = Getattr(n, "sym:name");
int result = Language::staticmemberfunctionHandler(n); int result = Language::staticmemberfunctionHandler(n);
if (cparse_cplusplus && getCurrentClass()) { if (cparse_cplusplus && getCurrentClass()) {
Swig_restore(n); Swig_restore(n);
} }
current = NO_CPP; current[STATIC_FUNC] = false;;
if (result != SWIG_OK) if (result != SWIG_OK)
return result; return result;
if (Getattr(n, "sym:nextSibling")) if (Getattr(n, "sym:nextSibling"))
return SWIG_OK; return SWIG_OK;
Swig_require("luaclassobj_staticmemberfunctionHandler", n, "luaclassobj:wrap:name", NIL); //Swig_require("luaclassobj_staticmemberfunctionHandler", n, "luaclassobj:wrap:name", NIL);
//String *name = Getattr(n, "name"); //String *name = Getattr(n, "name");
//String *rname, *realname; //String *rname, *realname;
//realname = symname ? symname : name; //realname = symname ? symname : name;
//rname = Getattr(n, "luaclassobj:wrap:name"); //rname = Getattr(n, "luaclassobj:wrap:name");
// TODO: Add backward compatibility here: add "ClassName_FuncName" to global table // TODO: Add backward compatibility here: add "ClassName_FuncName" to global table
//Printv(s_cls_methods_tab, tab4, "{\"", realname, "\", ", rname, "}, \n", NIL); //Printv(s_cls_methods_tab, tab4, "{\"", realname, "\", ", rname, "}, \n", NIL);
Swig_restore(n); //Swig_restore(n);
return SWIG_OK; return SWIG_OK;
} }
@ -1454,7 +1537,7 @@ public:
} }
int result = Language::memberconstantHandler(n); int result = Language::memberconstantHandler(n);
if (cparse_cplusplus && getCurrentClass()) if (cparse_cplusplus && getCurrentClass())
Swig_restore(n); Swig_restore(n); // TODO: WTF ?
return result; return result;
} }
@ -1465,9 +1548,10 @@ public:
virtual int staticmembervariableHandler(Node *n) { virtual int staticmembervariableHandler(Node *n) {
REPORT("staticmembervariableHandler",n); REPORT("staticmembervariableHandler",n);
current = STATIC_VAR; current[STATIC_VAR] = true;
//String *symname = Getattr(n, "sym:name"); //String *symname = Getattr(n, "sym:name");
int result = Language::staticmembervariableHandler(n); int result = Language::staticmembervariableHandler(n);
current[STATIC_VAR] = false;
if (result != SWIG_OK) if (result != SWIG_OK)
return result; return result;
@ -1868,6 +1952,53 @@ public:
Printf( output, "static swig_lua_namespace %s;\n", Getattr(nspace_hash, "cname") ); Printf( output, "static swig_lua_namespace %s;\n", Getattr(nspace_hash, "cname") );
} }
// Our implementation of addSymbol. Determines scope correctly, then calls Language::addSymbol
int luaAddSymbol(const String *s, const Node *n) {
String* scope = 0;
// If ouside class, than NSpace is used.
if( !getCurrentClass())
scope = getNSpace();
else {
// If inside class, then either class static namespace or class fully qualified name is used
assert(!current[NO_CPP]);
if(current[STATIC_FUNC] || current[STATIC_VAR] || current[STATIC_CONST] ) {
scope = class_static_nspace;
} else if(current[MEMBER_VAR] || current[CLASS_CONST] || current[CONSTRUCTOR] || current[DESTRUCTOR]
|| current[MEMBER_FUNC] ) {
scope = class_fq_symname;
} else {
assert(0); // Can't be. Implementation error
}
assert(scope != 0);
}
return Language::addSymbol(s,n,scope);
}
// Overload. Enforces given scope. Actually, it simply forwards call to Language::addSymbol
int luaAddSymbol(const String*s, const Node*n, const_String_or_char_ptr scope) {
return Language::addSymbol(s,n,scope);
}
// Function creates fully qualified name of given symbol. Current NSpace and current class
// are used
String* fully_qualified_name(const_String_or_char_ptr name)
{
assert(name != 0);
String* scope= 0;
if( getCurrentClass() )
scope = class_fq_symname;
else
scope = getNSpace();
String *fqname = 0;
if( scope )
fqname = NewStringf("%s::%s",scope,name);
else
fqname = Copy(name);
return fqname;
}
}; };
/* NEW LANGUAGE NOTE:*********************************************** /* NEW LANGUAGE NOTE:***********************************************