From 705beb67530f6bbbdd85a776831dbd48be675262 Mon Sep 17 00:00:00 2001 From: Artem Serebriyskiy Date: Sun, 17 Nov 2013 01:11:50 +0400 Subject: [PATCH] Bugfixes for eLua. eLua emulation mode --- Examples/test-suite/lua/grouping_runme.lua | 1 + Examples/test-suite/lua/newobject1_runme.lua | 4 +- Lib/lua/luarun.swg | 311 ++++++++++++++++++- Lib/lua/luaruntime.swg | 23 +- Source/Modules/lua.cxx | 189 +++++++---- 5 files changed, 445 insertions(+), 83 deletions(-) diff --git a/Examples/test-suite/lua/grouping_runme.lua b/Examples/test-suite/lua/grouping_runme.lua index 7ab08499f..b13409514 100644 --- a/Examples/test-suite/lua/grouping_runme.lua +++ b/Examples/test-suite/lua/grouping_runme.lua @@ -14,4 +14,5 @@ assert(g.test3 == 37) g.test3 = 42 assert(g.test3 == 42) +assert(g.NEGATE ~= nil) assert(g.do_unary(5, g.NEGATE) == -5) diff --git a/Examples/test-suite/lua/newobject1_runme.lua b/Examples/test-suite/lua/newobject1_runme.lua index 5de8276db..55d04eeb7 100644 --- a/Examples/test-suite/lua/newobject1_runme.lua +++ b/Examples/test-suite/lua/newobject1_runme.lua @@ -1,8 +1,8 @@ require("import") -- the import fn import("newobject1") -- import code -foo1 = newobject1.Foo_makeFoo() -- lua doesnt yet support static fns properly -assert(newobject1.Foo_fooCount() == 1) -- lua doesnt yet support static fns properly +foo1 = newobject1.Foo_makeFoo() +assert(newobject1.Foo_fooCount() == 1) foo2 = foo1:makeMore() assert(newobject1.Foo_fooCount() == 2) diff --git a/Lib/lua/luarun.swg b/Lib/lua/luarun.swg index 9f5bf5869..9f8f69476 100644 --- a/Lib/lua/luarun.swg +++ b/Lib/lua/luarun.swg @@ -27,14 +27,80 @@ extern "C" { # error SWIG_LUA_TARGET not defined #endif +#if defined(SWIG_LUA_ELUA_EMULATE) + +struct swig_elua_entry; + +typedef struct swig_elua_key { + int type; + union { + const char* strkey; + lua_Number numkey; + } key; +} swig_elua_key; + +typedef struct swig_elua_val { + int type; + union { + lua_Number number; + const struct swig_elua_entry *table; + const char *string; + lua_CFunction function; + struct { + char member; + long lvalue; + void *pvalue; + swig_type_info **ptype; + } userdata; + } value; +} swig_elua_val; + +typedef struct swig_elua_entry { + swig_elua_key key; + swig_elua_val value; +} swig_elua_entry; + +#define LSTRKEY(x) {LUA_TSTRING, {.strkey = x} } +#define LNUMKEY(x) {LUA_TNUMBER, {.numkey = x} } +#define LNILKEY {LUA_TNIL, {.strkey = 0} } + +#define LNUMVAL(x) {LUA_TNUMBER, {.number = x} } +#define LFUNCVAL(x) {LUA_TFUNCTION, {.function = x} } +#define LROVAL(x) {LUA_TTABLE, {.table = x} } +#define LNILVAL {LUA_TNIL, {.string = 0} } +#define LSTRVAL(x) {LUA_TSTRING, {.string = x} } + +#define LUA_REG_TYPE swig_elua_entry + +#define SWIG_LUA_ELUA_EMUL_METATABLE_KEY "__metatable" + +#define lua_pushrotable(L,p)\ + lua_newtable(L);\ + SWIG_Lua_elua_emulate_register(L,p); + +#define SWIG_LUA_CONSTTAB_POINTER(B,C,D)\ + LSTRKEY(B), {LUA_TUSERDATA, { .userdata={0,0,(void*)(C),&D} } } + +#define SWIG_LUA_CONSTTAB_BINARY(B,S,C,D)\ + LSTRKEY(B), {LUA_TUSERDATA, { .userdata={1,S,(void*)(C),&D} } } +#endif + #if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC) # define SWIG_LUA_CONSTTAB_INT(B, C) LSTRKEY(B), LNUMVAL(C) # define SWIG_LUA_CONSTTAB_FLOAT(B, C) LSTRKEY(B), LNUMVAL(C) # define SWIG_LUA_CONSTTAB_STRING(B, C) LSTRKEY(B), LSTRVAL(C) # define SWIG_LUA_CONSTTAB_CHAR(B, C) LSTRKEY(B), LNUMVAL(C) /* Those two types of constants are not supported in elua */ -# define SWIG_LUA_CONSTTAB_POINTER(B,C,D) LSTRKEY(B), LNILVAL -# define SWIG_LUA_CONSTTAB_BINARY(B, S, C, D) LSTRKEY(B), LNILVAL + +#ifndef SWIG_LUA_CONSTTAB_POINTER +#warning eLua does not support pointers as constants. By default, nil will be used as value +#define SWIG_LUA_CONSTTAB_POINTER(B,C,D) LSTRKEY(B), LNILVAL +#endif + +#ifndef SWIG_LUA_CONSTTAB_BINARY +#warning eLua does not support pointers to member as constants. By default, nil will be used as value +#define SWIG_LUA_CONSTTAB_BINARY(B, S, C, D) LSTRKEY(B), LNILVAL +#endif #else /* SWIG_LUA_FLAVOR_LUA */ # define SWIG_LUA_CONSTTAB_INT(B, C) SWIG_LUA_INT, (char *)B, (long)C, 0, 0, 0 # define SWIG_LUA_CONSTTAB_FLOAT(B, C) SWIG_LUA_FLOAT, (char *)B, 0, (double)C, 0, 0 @@ -46,15 +112,19 @@ extern "C" { SWIG_LUA_BINARY, (char *)B, S, 0, (void *)C, &D #endif +#ifndef SWIG_LUA_ELUA_EMULATE #if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC) # define LRO_STRVAL(v) {{.p = (char *) v}, LUA_TSTRING} # define LSTRVAL LRO_STRVAL #endif +#endif /* SWIG_LUA_ELUA_EMULATE*/ +#ifndef SWIG_LUA_ELUA_EMULATE #if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC) #include "lrodefs.h" #include "lrotable.h" #endif +#endif /* SWIG_LUA_ELUA_EMULATE*/ /* ----------------------------------------------------------------------------- * compatibility defines * ----------------------------------------------------------------------------- */ @@ -86,6 +156,19 @@ extern "C" { # define lua_absindex(L,i) ((i)>0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1) #endif +/* lua_rawsetp was introduced in Lua 5.2 */ +#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502 +#define lua_rawsetp(L,index,ptr)\ + lua_pushlightuserdata(L,(void*)(ptr));\ + lua_insert(L,-2);\ + lua_rawset(L,index); + +#define lua_rawgetp(L,index,ptr)\ + lua_pushlightuserdata(L,(void*)(ptr));\ + lua_rawget(L,index); + +#endif + /* -------------------------------------------------------------------------- * Helper functions for error handling * -------------------------------------------------------------------------- */ @@ -179,6 +262,7 @@ typedef struct swig_lua_class { swig_lua_method *methods; swig_lua_attribute *attributes; swig_lua_namespace *cls_static; + swig_lua_method *metatable; // only for eLua struct swig_lua_class **bases; const char **base_names; } swig_lua_class; @@ -288,6 +372,179 @@ SWIGINTERN int SWIG_Lua_set_immutable(lua_State *L) return 0; /* should not return anything */ } +#ifdef SWIG_LUA_ELUA_EMULATE +//#define report(...) printf(__VA_ARGS__) // TODO: REMOVE +#define report(...) // TODO : REMOVE + +SWIGRUNTIME void SWIG_Lua_NewPointerObj(lua_State *L,void *ptr,swig_type_info *type, int own); +SWIGRUNTIME void SWIG_Lua_NewPackedObj(lua_State *L,void *ptr,size_t size,swig_type_info *type); +static int swig_lua_elua_emulate_unique_key; +/* This is function that emulates eLua rotables behaviour. It loads rotable definition + * into the usual lua table. + */ +SWIGINTERN void SWIG_Lua_elua_emulate_register(lua_State *L, const swig_elua_entry *table) +{ + assert(lua_istable(L,-1)); + int target_table = lua_gettop(L); + /* Get the registry where we put all parsed tables to avoid loops */ + lua_rawgetp(L, LUA_REGISTRYINDEX, &swig_lua_elua_emulate_unique_key); + if(lua_isnil(L,-1)) { + lua_pop(L,1); + lua_newtable(L); + lua_pushvalue(L,-1); + lua_rawsetp(L,LUA_REGISTRYINDEX,(void*)(&swig_lua_elua_emulate_unique_key)); + } + int parsed_tables_array = lua_gettop(L); + lua_pushvalue(L,target_table); + lua_rawsetp(L, parsed_tables_array, table); + int i; + int table_parsed = 0; + int pairs_start = lua_gettop(L); + static int tabs_count = 0; // TODO: REMOVE + for(i = 0;table[i].key.type != LUA_TNIL || table[i].value.type != LUA_TNIL;i++) + { + /* TODO: REMOVE */ + int j = 0; + for(j=0;jkey.type) { + case LUA_TSTRING: + lua_pushstring(L,entry->key.key.strkey); + report(" %s :", entry->key.key.strkey); // TODO: REMOVE + if(strcmp(entry->key.key.strkey, SWIG_LUA_ELUA_EMUL_METATABLE_KEY) == 0) + is_metatable = 1; + break; + case LUA_TNUMBER: + lua_pushnumber(L,entry->key.key.numkey); + report(" %f :", (double)(entry->key.key.numkey)); // TODO: REMOVE + break; + case LUA_TNIL: + report(" nil :"); // TODO: REMOVE + lua_pushnil(L); + break; + default: + assert(0); + } + switch(entry->value.type) { + case LUA_TSTRING: + lua_pushstring(L,entry->value.value.string); + report(" %s", entry->value.value.string); // TODO: REMOVE + break; + case LUA_TNUMBER: + lua_pushnumber(L,entry->value.value.number); + report(" %f", (double)(entry->value.value.number)); // TODO: REMOVE + break; + case LUA_TFUNCTION: + report(" %p", (void*)(entry->value.value.function)); // TODO: REMOVE + lua_pushcfunction(L,entry->value.value.function); + break; + case LUA_TTABLE: + /* TODO: REMOVE */ + report(" table"); + tabs_count++; + /* END OF REMOVE */ + lua_rawgetp(L,parsed_tables_array, entry->value.value.table); + table_parsed = !lua_isnil(L,-1); + if(!table_parsed) { + lua_pop(L,1); /*remove nil */ + report("\n"); // TODO: REMOVE + lua_newtable(L); + SWIG_Lua_elua_emulate_register(L,entry->value.value.table); + } else { + report(" already parsed"); // TODO: REMOVE + } + if(is_metatable) { + report(" (registering metatable)"); // TODO: REMOVE + assert(lua_istable(L,-1)); + lua_pushvalue(L,-1); + lua_setmetatable(L,target_table); + } + + tabs_count--; /*TODO: REMOVE*/ + break; + case LUA_TUSERDATA: + if(entry->value.value.userdata.member) + SWIG_NewMemberObj(L,entry->value.value.userdata.pvalue, + entry->value.value.userdata.lvalue, + *(entry->value.value.userdata.ptype)); + else + SWIG_NewPointerObj(L,entry->value.value.userdata.pvalue, + *(entry->value.value.userdata.ptype),0); + break; + case LUA_TNIL: + report(" nil"); // TODO: REMOVE + lua_pushnil(L); + break; + default: + assert(0); + } + assert(lua_gettop(L) == pairs_start + 2); + lua_rawset(L,target_table); + report("\n"); // TODO: REMOVE + } + lua_pop(L,1); /* Removing parsed tables storage */ + assert(lua_gettop(L) == target_table); +} + +SWIGINTERN void SWIG_Lua_elua_emulate_register_clear(lua_State *L) +{ + lua_pushnil(L); + lua_rawsetp(L, LUA_REGISTRYINDEX, &swig_lua_elua_emulate_unique_key); +} + +/* TODO: REMOVE */ +SWIGINTERN void SWIG_Lua_get_class_registry(lua_State *L); + +SWIGINTERN int SWIG_Lua_emulate_elua_getmetatable(lua_State *L) +{ + SWIG_check_num_args("getmetatable(SWIG eLua emulation)", 1, 1); + SWIG_Lua_get_class_registry(L); + lua_getfield(L,-1,"lua_getmetatable"); + lua_remove(L,-2); /* remove the registry*/ + assert(!lua_isnil(L,-1)); + lua_pushvalue(L,1); + assert(lua_gettop(L) == 3); /* object | function | object again */ + lua_call(L,1,1); + if(!lua_isnil(L,-1)) /*There is an ordinary metatable */ + return 1; + /*if it is a table, then emulate elua behaviour - check for __metatable attribute of a table*/ + assert(lua_gettop(L) == 2); + if(lua_istable(L,-2)) { + printf("getmetatable: elua emulation part\n"); // TODO: REMOVE + lua_pop(L,1); /*remove the nil*/ + lua_getfield(L,-1, SWIG_LUA_ELUA_EMUL_METATABLE_KEY); + } + assert(lua_gettop(L) == 2); + return 1; + +fail: + lua_error(L); + return 0; +} + +SWIGINTERN void SWIG_Lua_emulate_elua_swap_getmetatable(lua_State *L) +{ + int begin = lua_gettop(L); // TODO: REMOVE + SWIG_Lua_get_class_registry(L); + lua_pushglobaltable(L); + lua_pushstring(L,"lua_getmetatable"); + lua_getfield(L,-2,"getmetatable"); + assert(!lua_isnil(L,-1)); + lua_rawset(L,-4); + lua_pushstring(L, "getmetatable"); + lua_pushcfunction(L, SWIG_Lua_emulate_elua_getmetatable); + lua_rawset(L,-3); + lua_pop(L,2); + assert(lua_gettop(L) == begin); // TODO: REMOVE + +} +/* END OF REMOVE */ + +#endif /* ----------------------------------------------------------------------------- * global variable support code: namespaces and modules (which are the same thing) * ----------------------------------------------------------------------------- */ @@ -415,6 +672,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, int reg) { + /* 1 argument - table on the top of the stack */ int begin = lua_gettop(L); assert(lua_istable(L,-1)); /* just in case. This is supposed to be module table or parent namespace table */ lua_checkstack(L,5); @@ -487,6 +745,7 @@ SWIGINTERN void SWIG_Lua_get_class_metatable(lua_State *L,const char *cname); #else /* en elua .bases table doesn't exist. Use table from swig_lua_class */ #define SWIG_LUA_INIT_BASE_SEARCH(bases_count)\ + assert(swig_type!=0);\ swig_module_info *module=SWIG_GetModule(L);\ swig_lua_class **bases= ((swig_lua_class*)(swig_type->clientdata))->bases;\ const char **base_names= ((swig_lua_class*)(swig_type->clientdata))->base_names;\ @@ -500,7 +759,8 @@ SWIGINTERN void SWIG_Lua_get_class_metatable(lua_State *L,const char *cname); else {\ valid = 1;\ SWIG_Lua_get_class_metatable(L,base_class->fqname);\ - base_swig_type = SWIG_TypeQueryModule(module,module,base_class->fqname);\ + base_swig_type = SWIG_TypeQueryModule(module,module,base_names[i]);\ + assert(base_swig_type != 0);\ } #endif @@ -989,14 +1249,11 @@ SWIGINTERN void SWIG_Lua_add_class_instance_details(lua_State *L,swig_lua_class } lua_pop(L,1); /* tidy stack (remove table) */ /* add operator overloads - these look ANY method which start with "__" and assume they - are operator overloads & add them to the metatable - (this might mess up if someone defines a method __gc (the destructor)*/ - for(i=0;clss->methods[i].name;i++){ - if (clss->methods[i].name[0]=='_' && clss->methods[i].name[1]=='_'){ - SWIG_Lua_add_function(L,clss->methods[i].name,clss->methods[i].func); - } - } + This adds methods from metatable array to metatable. Can mess up garbage + collectind if someone defines __gc method + */ + for(i=0;clss->metatable[i].name;i++) + SWIG_Lua_add_function(L,clss->metatable[i].name,clss->metatable[i].func); } /* Register class static methods,attributes etc as well as constructor proxy */ @@ -1152,6 +1409,38 @@ SWIGINTERN void SWIG_Lua_class_register(lua_State *L,swig_lua_class *clss) assert(lua_gettop(L) == begin); } #endif /* SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_LUA */ + +#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC) +SWIGINTERN void SWIG_Lua_elua_class_register_instance(lua_State *L, swig_lua_class *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 */ + 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_elua_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 */ + assert(clss->metatable); + lua_pushrotable(L, (void*)(clss->metatable)); /* create the metatable */ + lua_rawset(L,-3); + lua_pop(L,1); + assert(lua_gettop(L) == begin); +} +#endif // elua && eluac + /* ----------------------------------------------------------------------------- * Class/structure conversion fns * ----------------------------------------------------------------------------- */ diff --git a/Lib/lua/luaruntime.swg b/Lib/lua/luaruntime.swg index 52b698051..0f0cd5501 100644 --- a/Lib/lua/luaruntime.swg +++ b/Lib/lua/luaruntime.swg @@ -36,7 +36,7 @@ SWIGEXPORT int SWIG_init(lua_State* L) /* default Lua action */ SWIG_PropagateClientData(); #endif -#if ((SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUA) && (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC)) +#if ((SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUA) && (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC)) || defined(SWIG_LUA_ELUA_EMULATE) /* add a global fn */ SWIG_Lua_add_function(L,"swig_type",SWIG_Lua_type); SWIG_Lua_add_function(L,"swig_equals",SWIG_Lua_equal); @@ -56,7 +56,26 @@ SWIGEXPORT int SWIG_init(lua_State* L) /* default Lua action */ #if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_LUA) - SWIG_Lua_namespace_register(L,&swig___Global, globalRegister); + SWIG_Lua_namespace_register(L,&swig___Module, globalRegister); +#endif + +#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC) + for (i = 0; swig_types[i]; i++){ + if (swig_types[i]->clientdata){ + SWIG_Lua_elua_class_register_instance(L,(swig_lua_class*)(swig_types[i]->clientdata)); + } + } +#endif + +#if defined(SWIG_LUA_ELUA_EMULATE) + lua_newtable(L); + SWIG_Lua_elua_emulate_register(L,swig___Module.ns_methods); + SWIG_Lua_elua_emulate_register_clear(L); + if(globalRegister) { + lua_pushstring(L,swig___Module.name); + lua_pushvalue(L,-2); + lua_rawset(L,-4); + } #endif #endif diff --git a/Source/Modules/lua.cxx b/Source/Modules/lua.cxx index 1d7b831b1..c68782e75 100644 --- a/Source/Modules/lua.cxx +++ b/Source/Modules/lua.cxx @@ -90,12 +90,15 @@ Lua Options (available with -lua)\n\ -squash-bases - Squashes symbols from all inheritance tree of a given class\n\ into itself. Emulates pre-SWIG3.0 inheritance. Insignificantly\n\ speeds things up, but increases memory consumption.\n\ + -elua-emulate - Emulates behaviour of eLua. Usefull only for testing.\n\ + Incompatible with -elua/-eluac options.\n\ \n"; static int nomoduleglobal = 0; static int elua_ltr = 0; static int elua_opt_lvl = 2; static int eluac_ltr = 0; +static int elua_emulate = 0; static int squash_bases = 0; static int v2_compatibility = 0; static const int default_api_level = 2; @@ -239,10 +242,18 @@ public: } else if (strcmp(argv[i], "-squash-bases") == 0) { Swig_mark_arg(i); squash_bases = 1; + } else if (strcmp(argv[i], "-elua-emulate") == 0) { + Swig_mark_arg(i); + elua_emulate = 1; } } } + if (elua_emulate && (eluac_ltr || elua_ltr )) { + Printf(stderr, "Can't have -elua-emulate and -eluac/-elua at the same time\n"); + Swig_arg_error(); + } + // Set API-compatibility options if (api_level <= 2) // Must be compatible with SWIG 2.* v2_compatibility = 1; @@ -252,6 +263,9 @@ public: //if(api_level <= 4) // v4_compatibility = 1; + // Set elua_ltr if elua_emulate is requested + if(elua_emulate) + elua_ltr = 1; /* NEW LANGUAGE NOTE:*********************************************** This is the boilerplate code, setting a few #defines @@ -466,12 +480,21 @@ public: Hash *nspaceHash = getNamespaceHash(nspace_or_class_name); String *s_ns_methods_tab = Getattr(nspaceHash, "methods"); String *wname = Getattr(n, "wrap:name"); - String *iname = Getattr(n, "sym:name"); String *target_name = Getattr(n, "lua:name"); if (elua_ltr || eluac_ltr) - Printv(s_ns_methods_tab, tab4, "{LSTRKEY(\"", iname, "\")", ", LFUNCVAL(", wname, ")", "},\n", NIL); + Printv(s_ns_methods_tab, tab4, "{LSTRKEY(\"", target_name, "\")", ", LFUNCVAL(", wname, ")", "},\n", NIL); else Printv(s_ns_methods_tab, tab4, "{ \"", target_name, "\", ", wname, "},\n", NIL); + // Add to the metatable if method starts with '__' + const char * tn = Char(target_name); + if (tn[0]=='_' && tn[1] == '_' && !eluac_ltr) { + String *metatable_tab = Getattr(nspaceHash, "metatable"); + assert(metatable_tab); + if (elua_ltr) + Printv(metatable_tab, tab4, "{LSTRKEY(\"", target_name, "\")", ", LFUNCVAL(", wname, ")", "},\n", NIL); + else + Printv(metatable_tab, tab4, "{ \"", target_name, "\", ", wname, "},\n", NIL); + } } // Helper for functionWrapper - determines whether we should @@ -1147,7 +1170,7 @@ public: Printv(ns_classes, "&", wrap_class, ",\n", NIL); if (elua_ltr || eluac_ltr) { String *ns_methods = Getattr(nspaceHash, "methods"); - Hash *class_hash = getNamespaceHash(class_fq_symname); + Hash *class_hash = getNamespaceHash(class_static_nspace); assert(class_hash); String *cls_methods = Getattr(class_hash, "methods:name"); assert(cls_methods); @@ -1385,6 +1408,12 @@ public: Printf(f_wrappers, ",0"); } Printf(f_wrappers, ", %s, %s, &%s", s_methods_tab_name, s_attr_tab_name, Getattr(static_cls, "cname")); + + if (!eluac_ltr) + Printf(f_wrappers, ", %s", Getattr(instance_cls,"metatable:name")); + else + Printf(f_wrappers, ", 0"); + Printf(f_wrappers, ", swig_%s_bases, swig_%s_base_names };\n\n", mangled_class_fq_symname, mangled_class_fq_symname); current[NO_CPP] = true; @@ -1602,7 +1631,11 @@ public: * --------------------------------------------------------------------- */ void emitLuaFlavor(String *s) { - if (elua_ltr) + if (elua_emulate) { + Printf(s, "/*This is only emulation!*/\n"); + Printf(s, "#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_ELUA\n"); + Printf(s, "#define SWIG_LUA_ELUA_EMULATE\n"); + } else if (elua_ltr) Printf(s, "#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_ELUA\n"); else if (eluac_ltr) Printf(s, "#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_ELUAC\n"); @@ -1649,39 +1682,11 @@ public: nspace_hash = NewHash(); String *mangled_name = 0; if (nspace == 0 || Len(nspace) == 0) - mangled_name = NewString("__Global"); // C++ names can't start with "__ + capital letter" + mangled_name = NewString("__Module"); // C++ names can't start with "__ + capital letter" else mangled_name = Swig_name_mangle(nspace); String *cname = NewStringf("swig_%s", mangled_name); - if (reg && nspace != 0 && Len(nspace) != 0 && Getattr(nspace_hash, "lua:no_reg") == 0) { - // Split names into components - List *components = Split(nspace, '.', -1); - String *parent_path = NewString(""); - int len = Len(components); - String *name = Copy(Getitem(components, len - 1)); - for (int i = 0; i < len - 1; i++) { - if (i > 0) - Printv(parent_path, NSPACE_SEPARATOR, NIL); - String *item = Getitem(components, i); - Printv(parent_path, item, NIL); - } - //Printf(stdout, "Registering %s. User name %s. C-name %s, Parent is %s\n", mangled_name, name, cname, parent_path); // TODO: REMOVE - Hash *parent = getNamespaceHash(parent_path, true); - String *namespaces_tab = Getattr(parent, "namespaces"); - Printv(namespaces_tab, "&", cname, ",\n", NIL); - if (elua_ltr || eluac_ltr) { - String *methods_tab = Getattr(parent, "methods"); - Printv(methods_tab, tab4, "{LSTRKEY(\"", name, "\")", ", LROVAL(", cname, ")", "},\n", NIL); - } - Setattr(nspace_hash, "name", name); - - Delete(components); - Delete(parent_path); - } else if (!reg) // This namespace shouldn't be registered. Lets remember it - Setattr(nspace_hash, "lua:no_reg", "1"); - - Setattr(nspace_hash, "cname", cname); String *attr_tab = NewString(""); @@ -1766,23 +1771,52 @@ public: Setattr(nspace_hash, "set:name", set_tab_name); Setattr(nspace_hash, "set:decl", set_tab_decl); - if (!eluac_ltr) { - String *metatable_tab = NewString(""); - String *metatable_tab_name = NewStringf("swig_%s_meta", mangled_name); - String *metatable_tab_decl = NewString(""); - Printv(metatable_tab, "const LUA_REG_TYPE ", metatable_tab_name, "[]", NIL); - Printv(metatable_tab_decl, metatable_tab, ";", NIL); - Printv(metatable_tab, " = {\n", NIL); - Setattr(nspace_hash, "metatable", metatable_tab); - Setattr(nspace_hash, "metatable:name", metatable_tab_name); - Setattr(nspace_hash, "metatable:decl", metatable_tab_decl); - } + } + if (!eluac_ltr) { + String *metatable_tab = NewString(""); + String *metatable_tab_name = NewStringf("swig_%s_meta", mangled_name); + String *metatable_tab_decl = NewString(""); + Printv(metatable_tab, "swig_lua_method ", metatable_tab_name, "[]", NIL); + Printv(metatable_tab_decl, metatable_tab, ";", NIL); + Printv(metatable_tab, " = {\n", NIL); + Setattr(nspace_hash, "metatable", metatable_tab); + Setattr(nspace_hash, "metatable:name", metatable_tab_name); + Setattr(nspace_hash, "metatable:decl", metatable_tab_decl); } String *key = 0; if (nspace != 0) key = Copy(nspace); Setattr(namespaces_hash, key ? key : "", nspace_hash); + if (reg && nspace != 0 && Len(nspace) != 0 && Getattr(nspace_hash, "lua:no_reg") == 0) { + // Split names into components + List *components = Split(nspace, '.', -1); + String *parent_path = NewString(""); + int len = Len(components); + String *name = Copy(Getitem(components, len - 1)); + for (int i = 0; i < len - 1; i++) { + if (i > 0) + Printv(parent_path, NSPACE_SEPARATOR, NIL); + String *item = Getitem(components, i); + Printv(parent_path, item, NIL); + } + //Printf(stdout, "Registering %s. User name %s. C-name %s, Parent is %s\n", mangled_name, name, cname, parent_path); // TODO: REMOVE + Hash *parent = getNamespaceHash(parent_path, true); + String *namespaces_tab = Getattr(parent, "namespaces"); + Printv(namespaces_tab, "&", cname, ",\n", NIL); + if (elua_ltr || eluac_ltr) { + String *methods_tab = Getattr(parent, "methods"); + Printv(methods_tab, tab4, "{LSTRKEY(\"", name, "\")", ", LROVAL(", methods_tab_name, ")", "},\n", NIL); + } + Setattr(nspace_hash, "name", name); + + Delete(components); + Delete(parent_path); + } else if (!reg) // This namespace shouldn't be registered. Lets remember it + Setattr(nspace_hash, "lua:no_reg", "1"); + + + Delete(mangled_name); mangled_name = 0; return nspace_hash; @@ -1829,6 +1863,7 @@ public: if (elua_ltr) Printv(methods_tab, tab4, "{LSTRKEY(\"__metatable\"), LROVAL(", metatable_tab_name, ")},\n", NIL); + Printv(methods_tab, tab4, "{LSTRKEY(\"__disown\"), LFUNCVAL(SWIG_Lua_class_disown)},\n", NIL); Printv(methods_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL); } else Printf(methods_tab, " {0,0}\n};\n"); @@ -1847,41 +1882,59 @@ public: } if (elua_ltr) { String *get_tab = Getattr(nspace_hash, "get"); - String *get_tab_name = Getattr(nspace_hash, "get:name"); String *set_tab = Getattr(nspace_hash, "set"); - String *set_tab_name = Getattr(nspace_hash, "set:name"); Printv(get_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL); Printv(set_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL); Printv(output, get_tab, NIL); Printv(output, set_tab, NIL); + } + if (!eluac_ltr) { String *metatable_tab = Getattr(nspace_hash, "metatable"); assert(metatable_tab); - Printv(metatable_tab, tab4, "{LSTRKEY(\"__index\"), LFUNCVAL(SWIG_Lua_namespace_get)},\n", NIL); - Printv(metatable_tab, tab4, "{LSTRKEY(\"__newindex\"), LFUNCVAL(SWIG_Lua_namespace_set)},\n", NIL); - Printv(metatable_tab, tab4, "{LSTRKEY(\".get\"), LROVAL(", get_tab_name, ")},\n", NIL); - Printv(metatable_tab, tab4, "{LSTRKEY(\".set\"), LROVAL(", set_tab_name, ")},\n", NIL); - if (Getattr(nspace_hash, "lua:class_instance")) { - String *static_cls = Getattr(nspace_hash, "lua:class_instance:static_hash"); - assert(static_cls); - // static_cls is swig_lua_namespace. This structure can't be use with eLua(LTR) - // Instead structure describing its methods isused - String *static_cls_cname = Getattr(static_cls, "methods:name"); - assert(static_cls_cname); - Printv(metatable_tab, tab4, "{LSTRKEY(\".static\"), LROVAL(", static_cls_cname, ")},\n", NIL); - // Put forward declaration of this array - Printv(output, "extern ", Getattr(static_cls, "methods:decl"), "\n", NIL); - } else if (Getattr(nspace_hash, "lua:class_static")) { - Hash *instance_cls = Getattr(nspace_hash, "lua:class_static:instance_hash"); - assert(instance_cls); - String *instance_cls_metatable_name = Getattr(instance_cls, "metatable:name"); - assert(instance_cls_metatable_name); - Printv(metatable_tab, tab4, "{LSTRKEY(\".instance\"), LROVAL(", instance_cls_metatable_name, ")},\n", NIL); + if (elua_ltr) { + String *get_tab_name = Getattr(nspace_hash, "get:name"); + String *set_tab_name = Getattr(nspace_hash, "set:name"); + + if (Getattr(nspace_hash, "lua:class_instance")) { + Printv(metatable_tab, tab4, "{LSTRKEY(\"__index\"), LFUNCVAL(SWIG_Lua_class_get)},\n", NIL); + Printv(metatable_tab, tab4, "{LSTRKEY(\"__newindex\"), LFUNCVAL(SWIG_Lua_class_set)},\n", NIL); + } else { + Printv(metatable_tab, tab4, "{LSTRKEY(\"__index\"), LFUNCVAL(SWIG_Lua_namespace_get)},\n", NIL); + Printv(metatable_tab, tab4, "{LSTRKEY(\"__newindex\"), LFUNCVAL(SWIG_Lua_namespace_set)},\n", NIL); + } + + Printv(metatable_tab, tab4, "{LSTRKEY(\"__gc\"), LFUNCVAL(SWIG_Lua_class_destruct)},\n", NIL); + Printv(metatable_tab, tab4, "{LSTRKEY(\".get\"), LROVAL(", get_tab_name, ")},\n", NIL); + Printv(metatable_tab, tab4, "{LSTRKEY(\".set\"), LROVAL(", set_tab_name, ")},\n", NIL); + Printv(metatable_tab, tab4, "{LSTRKEY(\".fn\"), LROVAL(", Getattr(nspace_hash, "methods:name"), ")},\n", NIL); + + if (Getattr(nspace_hash, "lua:class_instance")) { + String *static_cls = Getattr(nspace_hash, "lua:class_instance:static_hash"); + assert(static_cls); + // static_cls is swig_lua_namespace. This structure can't be use with eLua(LTR) + // Instead structure describing its methods isused + String *static_cls_cname = Getattr(static_cls, "methods:name"); + assert(static_cls_cname); + Printv(metatable_tab, tab4, "{LSTRKEY(\".static\"), LROVAL(", static_cls_cname, ")},\n", NIL); + // Put forward declaration of this array + Printv(output, "extern ", Getattr(static_cls, "methods:decl"), "\n", NIL); + } else if (Getattr(nspace_hash, "lua:class_static")) { + Hash *instance_cls = Getattr(nspace_hash, "lua:class_static:instance_hash"); + assert(instance_cls); + String *instance_cls_metatable_name = Getattr(instance_cls, "metatable:name"); + assert(instance_cls_metatable_name); + Printv(metatable_tab, tab4, "{LSTRKEY(\".instance\"), LROVAL(", instance_cls_metatable_name, ")},\n", NIL); + } + + Printv(metatable_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL); + } else { + Printf(metatable_tab, " {0,0}\n};\n"); } - Printv(metatable_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL); Printv(output, metatable_tab, NIL); } + Printv(output, "\n", NIL); } @@ -1896,7 +1949,7 @@ public: void closeNamespaces(File *dataOutput) { // Special handling for empty module. if (Getattr(namespaces_hash, "") == 0) { - // Module is empty. Create hash for global scope in order to have swig__Global + // Module is empty. Create hash for global scope in order to have swig__Module // variable in resulting file getNamespaceHash(0); }