Eliminating namespaces_hash and using symbols table instead

This commit is contained in:
Artem Serebriyskiy 2013-12-25 17:50:22 +04:00
commit e6d0f1327b
3 changed files with 209 additions and 125 deletions

View file

@ -319,8 +319,7 @@ overloading(0),
multiinput(0), multiinput(0),
cplus_runtime(0), cplus_runtime(0),
directors(0) { directors(0) {
Hash *symbols = NewHash(); addScope(""); // create top level/global symbol table scope
Setattr(symtabs, "", symbols); // create top level/global symbol table scope
argc_template_string = NewString("argc"); argc_template_string = NewString("argc");
argv_template_string = NewString("argv[%d]"); argv_template_string = NewString("argv[%d]");
@ -3061,9 +3060,7 @@ int Language::addSymbol(const String *s, const Node *n, const_String_or_char_ptr
//Printf( stdout, "addSymbol: %s %s\n", s, scope ); //Printf( stdout, "addSymbol: %s %s\n", s, scope );
Hash *symbols = Getattr(symtabs, scope ? scope : ""); Hash *symbols = Getattr(symtabs, scope ? scope : "");
if (!symbols) { if (!symbols) {
// New scope which has not been added by the target language - lazily created. symbols = addScope(scope);
symbols = NewHash();
Setattr(symtabs, scope, symbols);
} else { } else {
Node *c = Getattr(symbols, s); Node *c = Getattr(symbols, s);
if (c && (c != n)) { if (c && (c != n)) {
@ -3079,6 +3076,71 @@ int Language::addSymbol(const String *s, const Node *n, const_String_or_char_ptr
return 1; return 1;
} }
/* -----------------------------------------------------------------------------
* Lanugage::addScope( const_String_or_char_ptr scopeName )
*
* Creates a scope (symbols Hash) for given name. This method is auxilary,
* you don't have to call it - addSymbols will lazily create scopes automatically.
* If scope with given name already exists, then do nothing.
* Returns newly created (or already existing) scope.
* ----------------------------------------------------------------------------- */
Hash* Language::addScope(const_String_or_char_ptr scope) {
Hash *symbols = scopeLookup(scope);
if(!symbols) {
// Order in which to following parts are executed is important. In Lanugage
// constructor addScope("") is called to create a top level scope itself.
// Thus we must first add symbols hash to symtab and only then add pseudo
// symbol to top-level scope
// New scope which has not been added by the target language - lazily created.
symbols = NewHash();
Setattr(symtabs, scope, symbols);
// Add the new scope as a symbol in the top level scope.
// Alternatively the target language must add it in before attempting to add symbols into the scope.
const_String_or_char_ptr top_scope = "";
Hash *topscope_symbols = Getattr(symtabs, top_scope);
Hash *pseudo_symbol = NewHash();
Setattr(pseudo_symbol, "sym:is_scope", "1");
Setattr(topscope_symbols, scope, pseudo_symbol);
}
return symbols;
}
/* -----------------------------------------------------------------------------
* Lanugage::scopeLookup( const_String_or_char_ptr scope )
*
* Lookup and returns a symtable (hash) representing given scope. Hash contains
* all symbols in this scope.
* ----------------------------------------------------------------------------- */
Hash* Language::scopeLookup( const_String_or_char_ptr scope ) {
Hash *symbols = Getattr(symtabs, scope ? scope : "");
return symbols;
}
/* -----------------------------------------------------------------------------
* Lanugage::scopeSymbolLookup( const_String_or_char_ptr scope )
*
* For every scope there is a special pseudo-symbol in the top scope (""). It
* exists solely to detect name clashes. This pseudo symbol may contain a few properties,
* but you can more if you need to. This is also true fro top level scope ("").
* It contains a pseudo symbol with name "" (empty). Pseudo symbol contains the
* following properties:
* sym:scope = "1" - a flag that this is scope pseudo symbol
*
* Pseudo symbols are a Hash*, not a Node* (not that there is a difference
* in DOH)
* There is no difference from symbolLookup() method except for signature
* and return type.
* ----------------------------------------------------------------------------- */
Hash* Language::scopeSymbolLookup( const_String_or_char_ptr scope )
{
/* Getting top scope */
const_String_or_char_ptr top_scope = "";
Hash *symbols = Getattr(symtabs, top_scope);
return Getattr(symbols, scope);
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Language::dumpSymbols() * Language::dumpSymbols()
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */

View file

@ -120,7 +120,6 @@ private:
File *f_initbeforefunc; File *f_initbeforefunc;
String *s_luacode; // luacode to be called during init String *s_luacode; // luacode to be called during init
String *module; //name of the module String *module; //name of the module
Hash *namespaces_hash;
// Parameters for current class. NIL if not parsing class // Parameters for current class. NIL if not parsing class
int have_constructor; int have_constructor;
@ -176,13 +175,10 @@ public:
class_fq_symname(0), class_fq_symname(0),
class_static_nspace(0), class_static_nspace(0),
constructor_name(0) { constructor_name(0) {
namespaces_hash = NewHash();
for (int i = 0; i < STATES_COUNT; i++) for (int i = 0; i < STATES_COUNT; i++)
current[i] = false; current[i] = false;
} }
~LUA() { ~LUA() {
if (namespaces_hash)
Delete(namespaces_hash);
} }
bool strToInt(const char *string, int &value) { bool strToInt(const char *string, int &value) {
@ -477,7 +473,7 @@ public:
// Add method to the "methods" C array of given namespace/class // Add method to the "methods" C array of given namespace/class
void registerMethod(String *nspace_or_class_name, Node *n) { void registerMethod(String *nspace_or_class_name, Node *n) {
assert(n); assert(n);
Hash *nspaceHash = getNamespaceHash(nspace_or_class_name); Hash *nspaceHash = getCArraysHash(nspace_or_class_name);
String *s_ns_methods_tab = Getattr(nspaceHash, "methods"); String *s_ns_methods_tab = Getattr(nspaceHash, "methods");
String *wname = Getattr(n, "wrap:name"); String *wname = Getattr(n, "wrap:name");
String *target_name = Getattr(n, "lua:name"); String *target_name = Getattr(n, "lua:name");
@ -922,7 +918,7 @@ public:
if (setName == 0 || GetFlag(n, "feature:immutable")) { if (setName == 0 || GetFlag(n, "feature:immutable")) {
setName = unassignable; setName = unassignable;
} }
Hash *nspaceHash = getNamespaceHash(nspace_or_class_name); Hash *nspaceHash = getCArraysHash(nspace_or_class_name);
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");
String *target_name = Getattr(n, "lua:name"); String *target_name = Getattr(n, "lua:name");
@ -968,7 +964,7 @@ public:
* Actually, in current implementation it is resolved consttab typemap * Actually, in current implementation it is resolved consttab typemap
* ------------------------------------------------------------ */ * ------------------------------------------------------------ */
void registerConstant(String *nspace, String *constantRecord) { void registerConstant(String *nspace, String *constantRecord) {
Hash *nspaceHash = getNamespaceHash(nspace); Hash *nspaceHash = getCArraysHash(nspace);
String *s_const_tab = 0; String *s_const_tab = 0;
if (eluac_ltr || elua_ltr) if (eluac_ltr || elua_ltr)
// In elua everything goes to "methods" tab // In elua everything goes to "methods" tab
@ -1102,7 +1098,7 @@ public:
if (!luaAddSymbol(wrapname, n)) if (!luaAddSymbol(wrapname, n))
return SWIG_ERROR; return SWIG_ERROR;
Hash *nspaceHash = getNamespaceHash(getNSpace()); Hash *nspaceHash = getCArraysHash(getNSpace());
String *s_ns_methods_tab = Getattr(nspaceHash, "methods"); String *s_ns_methods_tab = Getattr(nspaceHash, "methods");
Printv(s_ns_methods_tab, tab4, "{ \"", symname, "\",", wrapname, "},\n", NIL); Printv(s_ns_methods_tab, tab4, "{ \"", symname, "\",", wrapname, "},\n", NIL);
// return Language::nativeWrapper(n); // this does nothing... // return Language::nativeWrapper(n); // this does nothing...
@ -1165,12 +1161,12 @@ public:
void registerClass(String *scope, Node *n) { void registerClass(String *scope, Node *n) {
String *wrap_class = Getattr(n,"wrap:class_name"); String *wrap_class = Getattr(n,"wrap:class_name");
assert(wrap_class); assert(wrap_class);
Hash *nspaceHash = getNamespaceHash(scope); Hash *nspaceHash = getCArraysHash(scope);
String *ns_classes = Getattr(nspaceHash, "classes"); String *ns_classes = Getattr(nspaceHash, "classes");
Printv(ns_classes, "&", wrap_class, ",\n", NIL); Printv(ns_classes, "&", wrap_class, ",\n", NIL);
if (elua_ltr || eluac_ltr) { if (elua_ltr || eluac_ltr) {
String *ns_methods = Getattr(nspaceHash, "methods"); String *ns_methods = Getattr(nspaceHash, "methods");
Hash *class_hash = getNamespaceHash(class_static_nspace); Hash *class_hash = getCArraysHash(class_static_nspace);
assert(class_hash); assert(class_hash);
String *cls_methods = Getattr(class_hash, "methods:name"); String *cls_methods = Getattr(class_hash, "methods:name");
assert(cls_methods); assert(cls_methods);
@ -1240,14 +1236,14 @@ public:
// 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'
// Now, here is a trick. Static methods, attributes and non-static methods and attributes // Now, here is a trick. Static methods, attributes and non-static methods and attributes
// are described with same structures - swig_lua_attribute/swig_lua_method. Instead of calling // are described with same structures - swig_lua_attribute/swig_lua_method. Instead of calling
// getNamespaceHash(class name) to initialize things for static methods/attributes and then // getCArraysHash(class name) to initialize things for static methods/attributes and then
// manually doing same initialization for non-static methods, we call getNamespaceHash 2 times: // manually doing same initialization for non-static methods, we call getCArraysHash 2 times:
// 1) With name "class name" + "." + "__Static" to initialize static things // 1) With name "class name" + "." + "__Static" to initialize static things
// 2) With "class name" to initialize non-static things // 2) With "class name" to initialize non-static things
// 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 *instance_cls = getNamespaceHash(class_fq_symname, false); Hash *instance_cls = getCArraysHash(class_fq_symname, false);
assert(instance_cls); assert(instance_cls);
String *s_attr_tab_name = Getattr(instance_cls, "attributes:name"); String *s_attr_tab_name = Getattr(instance_cls, "attributes:name");
String *s_methods_tab_name = Getattr(instance_cls, "methods:name"); String *s_methods_tab_name = Getattr(instance_cls, "methods:name");
@ -1260,7 +1256,7 @@ public:
*/ */
class_static_nspace = NewStringf("%s%s__Static", class_fq_symname, NSPACE_SEPARATOR); class_static_nspace = NewStringf("%s%s__Static", class_fq_symname, NSPACE_SEPARATOR);
Hash *static_cls = getNamespaceHash(class_static_nspace, false); Hash *static_cls = getCArraysHash(class_static_nspace, false);
assert(static_cls); assert(static_cls);
Setattr(static_cls, "lua:no_namespaces", "1"); Setattr(static_cls, "lua:no_namespaces", "1");
Setattr(static_cls, "lua:class_static", "1"); Setattr(static_cls, "lua:class_static", "1");
@ -1272,8 +1268,6 @@ public:
/* There is no use for "classes" and "namespaces" arrays. Subclasses are not supported /* There is no use for "classes" and "namespaces" arrays. Subclasses are not supported
* by SWIG and namespaces couldn't be nested inside classes (C++ Standard) * by SWIG and namespaces couldn't be nested inside classes (C++ Standard)
*/ */
// Replacing namespace with namespace + class in order to static
// member be put inside class static area
class_parent_nspace = getNSpace(); class_parent_nspace = getNSpace();
// Generate normal wrappers // Generate normal wrappers
Language::classHandler(n); Language::classHandler(n);
@ -1293,7 +1287,7 @@ public:
// Adding class to apropriate namespace // Adding class to apropriate namespace
registerClass(nspace, n); registerClass(nspace, n);
Hash *nspaceHash = getNamespaceHash(nspace); Hash *nspaceHash = getCArraysHash(nspace);
// 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_class_fq_symname); // Printf(f_init,"SWIG_TypeClientData(SWIGTYPE%s, (void *) &_wrap_class_%s);\n", SwigType_manglestr(t), mangled_class_fq_symname);
@ -1349,8 +1343,8 @@ public:
} }
} }
closeNamespaceHash(class_fq_symname, f_wrappers); closeCArraysHash(class_fq_symname, f_wrappers);
closeNamespaceHash(class_static_nspace, f_wrappers); closeCArraysHash(class_static_nspace, f_wrappers);
// Handle inheritance // Handle inheritance
@ -1385,7 +1379,7 @@ public:
} }
} }
// First, print class static part // First, print class static part
printNamespaceDefinition(class_static_nspace, class_symname, f_wrappers); printCArraysDefinition(class_static_nspace, class_symname, f_wrappers);
assert(mangled_class_fq_symname); assert(mangled_class_fq_symname);
assert(base_class); assert(base_class);
@ -1670,10 +1664,24 @@ public:
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* getNamespaceHash() * rawGetCArraysHash(String *name)
*
* A small helper to hide impelementation of how CArrays hashes are stored
* ---------------------------------------------------------------------------- */
Hash *rawGetCArraysHash(const_String_or_char_ptr name) {
Hash *scope = scopeLookup( name ? name : "" );
if(!scope)
return 0;
Hash *carrays_hash = Getattr(scope, "lua:cdata");
return carrays_hash;
}
/* -----------------------------------------------------------------------------
* getCArraysHash()
* Each namespace can be described with hash that stores C arrays * Each namespace can be described with hash that stores C arrays
* where members of the namespace should be added. All these hashes are stored * where members of the namespace should be added. All these hashes are stored
* inside namespaces_hash. * inside symbols table, in pseudo-symbol for every namespace.
* nspace could be NULL (NSPACE_TODO), that means functions and variables and classes * nspace could be NULL (NSPACE_TODO), that means functions and variables and classes
* that are not in any namespace (this is default for SWIG unless %nspace feature is used) * that are not in any namespace (this is default for SWIG unless %nspace feature is used)
* You can later set some attributes that will affect behaviour of functions that use this hash: * You can later set some attributes that will affect behaviour of functions that use this hash:
@ -1685,11 +1693,17 @@ public:
* Namespace could be automatically registered to it's parent if 'reg' == true. It can be done * Namespace could be automatically registered to it's parent if 'reg' == true. It can be done
* only at first call (a.k.a when nspace is created). * only at first call (a.k.a when nspace is created).
* ---------------------------------------------------------------------------- */ * ---------------------------------------------------------------------------- */
Hash *getNamespaceHash(String *nspace, bool reg = true) { Hash *getCArraysHash(String *nspace, bool reg = true) {
Hash *nspace_hash = Getattr(namespaces_hash, nspace ? nspace : ""); Hash *scope = scopeLookup(nspace ? nspace : "");
if (nspace_hash != 0) if(!scope) {
return nspace_hash; addScope( nspace ? nspace : "" );
nspace_hash = NewHash(); scope = scopeLookup(nspace ? nspace : "");
assert(scope);
}
Hash *carrays_hash = Getattr(scope, "lua:cdata");
if (carrays_hash != 0)
return carrays_hash;
carrays_hash = NewHash();
String *mangled_name = 0; String *mangled_name = 0;
if (nspace == 0 || Len(nspace) == 0) if (nspace == 0 || Len(nspace) == 0)
mangled_name = NewString("__Module"); // C++ names can't start with "__ + capital letter" mangled_name = NewString("__Module"); // C++ names can't start with "__ + capital letter"
@ -1697,7 +1711,7 @@ public:
mangled_name = Swig_name_mangle(nspace); mangled_name = Swig_name_mangle(nspace);
String *cname = NewStringf("swig_%s", mangled_name); String *cname = NewStringf("swig_%s", mangled_name);
Setattr(nspace_hash, "cname", cname); Setattr(carrays_hash, "cname", cname);
String *attr_tab = NewString(""); String *attr_tab = NewString("");
String *attr_tab_name = NewStringf("swig_%s_attributes", mangled_name); String *attr_tab_name = NewStringf("swig_%s_attributes", mangled_name);
@ -1706,9 +1720,9 @@ public:
Printv(attr_tab, attr_tab_name, "[]", NIL); Printv(attr_tab, attr_tab_name, "[]", NIL);
Printv(attr_tab_decl, attr_tab, ";\n", NIL); Printv(attr_tab_decl, attr_tab, ";\n", NIL);
Printv(attr_tab, " = {\n", NIL); Printv(attr_tab, " = {\n", NIL);
Setattr(nspace_hash, "attributes", attr_tab); Setattr(carrays_hash, "attributes", attr_tab);
Setattr(nspace_hash, "attributes:name", attr_tab_name); Setattr(carrays_hash, "attributes:name", attr_tab_name);
Setattr(nspace_hash, "attributes:decl", attr_tab_decl); Setattr(carrays_hash, "attributes:decl", attr_tab_decl);
String *methods_tab = NewString(""); String *methods_tab = NewString("");
String *methods_tab_name = NewStringf("swig_%s_methods", mangled_name); String *methods_tab_name = NewStringf("swig_%s_methods", mangled_name);
@ -1720,9 +1734,9 @@ public:
Printv(methods_tab, methods_tab_name, "[]", NIL); Printv(methods_tab, methods_tab_name, "[]", NIL);
Printv(methods_tab_decl, methods_tab, ";\n", NIL); Printv(methods_tab_decl, methods_tab, ";\n", NIL);
Printv(methods_tab, "= {\n", NIL); Printv(methods_tab, "= {\n", NIL);
Setattr(nspace_hash, "methods", methods_tab); Setattr(carrays_hash, "methods", methods_tab);
Setattr(nspace_hash, "methods:name", methods_tab_name); Setattr(carrays_hash, "methods:name", methods_tab_name);
Setattr(nspace_hash, "methods:decl", methods_tab_decl); Setattr(carrays_hash, "methods:decl", methods_tab_decl);
String *const_tab = NewString(""); String *const_tab = NewString("");
String *const_tab_name = NewStringf("swig_%s_constants", mangled_name); String *const_tab_name = NewStringf("swig_%s_constants", mangled_name);
@ -1734,9 +1748,9 @@ public:
Printv(const_tab, const_tab_name, "[]", NIL); Printv(const_tab, const_tab_name, "[]", NIL);
Printv(const_tab_decl, const_tab, ";", NIL); Printv(const_tab_decl, const_tab, ";", NIL);
Printv(const_tab, "= {\n", NIL); Printv(const_tab, "= {\n", NIL);
Setattr(nspace_hash, "constants", const_tab); Setattr(carrays_hash, "constants", const_tab);
Setattr(nspace_hash, "constants:name", const_tab_name); Setattr(carrays_hash, "constants:name", const_tab_name);
Setattr(nspace_hash, "constants:decl", const_tab_decl); Setattr(carrays_hash, "constants:decl", const_tab_decl);
String *classes_tab = NewString(""); String *classes_tab = NewString("");
String *classes_tab_name = NewStringf("swig_%s_classes", mangled_name); String *classes_tab_name = NewStringf("swig_%s_classes", mangled_name);
@ -1745,9 +1759,9 @@ public:
Printv(classes_tab, classes_tab_name, "[]", NIL); Printv(classes_tab, classes_tab_name, "[]", NIL);
Printv(classes_tab_decl, classes_tab, ";", NIL); Printv(classes_tab_decl, classes_tab, ";", NIL);
Printv(classes_tab, "= {\n", NIL); Printv(classes_tab, "= {\n", NIL);
Setattr(nspace_hash, "classes", classes_tab); Setattr(carrays_hash, "classes", classes_tab);
Setattr(nspace_hash, "classes:name", classes_tab_name); Setattr(carrays_hash, "classes:name", classes_tab_name);
Setattr(nspace_hash, "classes:decl", classes_tab_decl); Setattr(carrays_hash, "classes:decl", classes_tab_decl);
String *namespaces_tab = NewString(""); String *namespaces_tab = NewString("");
String *namespaces_tab_name = NewStringf("swig_%s_namespaces", mangled_name); String *namespaces_tab_name = NewStringf("swig_%s_namespaces", mangled_name);
@ -1756,9 +1770,9 @@ public:
Printv(namespaces_tab, namespaces_tab_name, "[]", NIL); Printv(namespaces_tab, namespaces_tab_name, "[]", NIL);
Printv(namespaces_tab_decl, namespaces_tab, ";", NIL); Printv(namespaces_tab_decl, namespaces_tab, ";", NIL);
Printv(namespaces_tab, " = {\n", NIL); Printv(namespaces_tab, " = {\n", NIL);
Setattr(nspace_hash, "namespaces", namespaces_tab); Setattr(carrays_hash, "namespaces", namespaces_tab);
Setattr(nspace_hash, "namespaces:name", namespaces_tab_name); Setattr(carrays_hash, "namespaces:name", namespaces_tab_name);
Setattr(nspace_hash, "namespaces:decl", namespaces_tab_decl); Setattr(carrays_hash, "namespaces:decl", namespaces_tab_decl);
if (elua_ltr) { if (elua_ltr) {
String *get_tab = NewString(""); String *get_tab = NewString("");
@ -1767,9 +1781,9 @@ public:
Printv(get_tab, "const LUA_REG_TYPE ", get_tab_name, "[]", NIL); Printv(get_tab, "const LUA_REG_TYPE ", get_tab_name, "[]", NIL);
Printv(get_tab_decl, get_tab, ";", NIL); Printv(get_tab_decl, get_tab, ";", NIL);
Printv(get_tab, " = {\n", NIL); Printv(get_tab, " = {\n", NIL);
Setattr(nspace_hash, "get", get_tab); Setattr(carrays_hash, "get", get_tab);
Setattr(nspace_hash, "get:name", get_tab_name); Setattr(carrays_hash, "get:name", get_tab_name);
Setattr(nspace_hash, "get:decl", get_tab_decl); Setattr(carrays_hash, "get:decl", get_tab_decl);
String *set_tab = NewString(""); String *set_tab = NewString("");
String *set_tab_name = NewStringf("swig_%s_set", mangled_name); String *set_tab_name = NewStringf("swig_%s_set", mangled_name);
@ -1777,9 +1791,9 @@ public:
Printv(set_tab, "const LUA_REG_TYPE ", set_tab_name, "[]", NIL); Printv(set_tab, "const LUA_REG_TYPE ", set_tab_name, "[]", NIL);
Printv(set_tab_decl, set_tab, ";", NIL); Printv(set_tab_decl, set_tab, ";", NIL);
Printv(set_tab, " = {\n", NIL); Printv(set_tab, " = {\n", NIL);
Setattr(nspace_hash, "set", set_tab); Setattr(carrays_hash, "set", set_tab);
Setattr(nspace_hash, "set:name", set_tab_name); Setattr(carrays_hash, "set:name", set_tab_name);
Setattr(nspace_hash, "set:decl", set_tab_decl); Setattr(carrays_hash, "set:decl", set_tab_decl);
} }
if (!eluac_ltr) { if (!eluac_ltr) {
@ -1795,16 +1809,15 @@ public:
Printv(metatable_tab, metatable_tab_name, "[]", NIL); Printv(metatable_tab, metatable_tab_name, "[]", NIL);
Printv(metatable_tab_decl, metatable_tab, ";", NIL); Printv(metatable_tab_decl, metatable_tab, ";", NIL);
Printv(metatable_tab, " = {\n", NIL); Printv(metatable_tab, " = {\n", NIL);
Setattr(nspace_hash, "metatable", metatable_tab); Setattr(carrays_hash, "metatable", metatable_tab);
Setattr(nspace_hash, "metatable:name", metatable_tab_name); Setattr(carrays_hash, "metatable:name", metatable_tab_name);
Setattr(nspace_hash, "metatable:decl", metatable_tab_decl); Setattr(carrays_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) { Setattr(scope, "lua:cdata", carrays_hash);
assert(rawGetCArraysHash(nspace));
if (reg && nspace != 0 && Len(nspace) != 0 && Getattr(carrays_hash, "lua:no_reg") == 0) {
// Split names into components // Split names into components
List *components = Split(nspace, '.', -1); List *components = Split(nspace, '.', -1);
String *parent_path = NewString(""); String *parent_path = NewString("");
@ -1817,50 +1830,49 @@ public:
Printv(parent_path, item, NIL); 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 //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); Hash *parent = getCArraysHash(parent_path, true);
String *namespaces_tab = Getattr(parent, "namespaces"); String *namespaces_tab = Getattr(parent, "namespaces");
Printv(namespaces_tab, "&", cname, ",\n", NIL); Printv(namespaces_tab, "&", cname, ",\n", NIL);
if (elua_ltr || eluac_ltr) { if (elua_ltr || eluac_ltr) {
String *methods_tab = Getattr(parent, "methods"); String *methods_tab = Getattr(parent, "methods");
Printv(methods_tab, tab4, "{LSTRKEY(\"", name, "\")", ", LROVAL(", methods_tab_name, ")", "},\n", NIL); Printv(methods_tab, tab4, "{LSTRKEY(\"", name, "\")", ", LROVAL(", methods_tab_name, ")", "},\n", NIL);
} }
Setattr(nspace_hash, "name", name); Setattr(carrays_hash, "name", name);
Delete(components); Delete(components);
Delete(parent_path); Delete(parent_path);
} else if (!reg) // This namespace shouldn't be registered. Lets remember it } else if (!reg) // This namespace shouldn't be registered. Lets remember it
Setattr(nspace_hash, "lua:no_reg", "1"); Setattr(carrays_hash, "lua:no_reg", "1");
Delete(mangled_name); Delete(mangled_name);
mangled_name = 0; mangled_name = 0;
return nspace_hash; return carrays_hash;
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* closeNamespaceHash() * closeCArraysHash()
* Functions add end markers {0,0,...,0} to all arrays, prints them to * Functions add end markers {0,0,...,0} to all arrays, prints them to
* output and marks hash as closed (lua:closed). Consequent attempts to * output and marks hash as closed (lua:closed). Consequent attempts to
* close same hash will result in error * close same hash will result in error
* closeNamespaceHash DOES NOT print structure that describes namespace, it only * closeCArraysHash DOES NOT print structure that describes namespace, it only
* prints array. You can use printNamespaceDefinition to print structure. * prints array. You can use printCArraysDefinition to print structure.
* if "lua:no_namespaces" is set, then array for "namespaces" won't be printed * if "lua:no_namespaces" is set, then array for "namespaces" won't be printed
* if "lua:no_classes" is set, then array for "classes" won't be printed * if "lua:no_classes" is set, then array for "classes" won't be printed
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
void closeNamespaceHash(String *nspace, File *output) { void closeCArraysHash(String *nspace, File *output) {
Hash *nspace_hash = Getattr(namespaces_hash, nspace); Hash *carrays_hash = rawGetCArraysHash(nspace);
assert(nspace_hash); assert(carrays_hash);
assert(Getattr(nspace_hash, "lua:closed") == 0); assert(Getattr(carrays_hash, "lua:closed") == 0);
Setattr(nspace_hash, "lua:closed", "1"); Setattr(carrays_hash, "lua:closed", "1");
String *attr_tab = Getattr(nspace_hash, "attributes"); String *attr_tab = Getattr(carrays_hash, "attributes");
Printf(attr_tab, " {0,0,0}\n};\n"); Printf(attr_tab, " {0,0,0}\n};\n");
Printv(output, attr_tab, NIL); Printv(output, attr_tab, NIL);
String *const_tab = Getattr(nspace_hash, "constants"); String *const_tab = Getattr(carrays_hash, "constants");
String *const_tab_name = Getattr(nspace_hash, "constants:name"); String *const_tab_name = Getattr(carrays_hash, "constants:name");
if (elua_ltr || eluac_ltr) if (elua_ltr || eluac_ltr)
Printv(const_tab, tab4, "{LNILKEY, LNILVAL}\n", "};\n", NIL); Printv(const_tab, tab4, "{LNILKEY, LNILVAL}\n", "};\n", NIL);
else else
@ -1869,10 +1881,10 @@ public:
if (elua_ltr) { if (elua_ltr) {
// Put forward declaration of metatable array // Put forward declaration of metatable array
Printv(output, "extern ", Getattr(nspace_hash, "metatable:decl"), "\n", NIL); Printv(output, "extern ", Getattr(carrays_hash, "metatable:decl"), "\n", NIL);
} }
String *methods_tab = Getattr(nspace_hash, "methods"); String *methods_tab = Getattr(carrays_hash, "methods");
String *metatable_tab_name = Getattr(nspace_hash, "metatable:name"); String *metatable_tab_name = Getattr(carrays_hash, "metatable:name");
assert(methods_tab); // TODO: REMOVE assert(methods_tab); // TODO: REMOVE
if (elua_ltr || eluac_ltr) { if (elua_ltr || eluac_ltr) {
if (v2_compatibility) if (v2_compatibility)
@ -1888,20 +1900,20 @@ public:
Printf(methods_tab, " {0,0}\n};\n"); Printf(methods_tab, " {0,0}\n};\n");
Printv(output, methods_tab, NIL); Printv(output, methods_tab, NIL);
if (!Getattr(nspace_hash, "lua:no_classes")) { if (!Getattr(carrays_hash, "lua:no_classes")) {
String *classes_tab = Getattr(nspace_hash, "classes"); String *classes_tab = Getattr(carrays_hash, "classes");
Printf(classes_tab, " 0\n};\n"); Printf(classes_tab, " 0\n};\n");
Printv(output, classes_tab, NIL); Printv(output, classes_tab, NIL);
} }
if (!Getattr(nspace_hash, "lua:no_namespaces")) { if (!Getattr(carrays_hash, "lua:no_namespaces")) {
String *namespaces_tab = Getattr(nspace_hash, "namespaces"); String *namespaces_tab = Getattr(carrays_hash, "namespaces");
Printf(namespaces_tab, " 0\n};\n"); Printf(namespaces_tab, " 0\n};\n");
Printv(output, namespaces_tab, NIL); Printv(output, namespaces_tab, NIL);
} }
if (elua_ltr) { if (elua_ltr) {
String *get_tab = Getattr(nspace_hash, "get"); String *get_tab = Getattr(carrays_hash, "get");
String *set_tab = Getattr(nspace_hash, "set"); String *set_tab = Getattr(carrays_hash, "set");
Printv(get_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL); Printv(get_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL);
Printv(set_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL); Printv(set_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL);
Printv(output, get_tab, NIL); Printv(output, get_tab, NIL);
@ -1909,13 +1921,13 @@ public:
} }
if (!eluac_ltr) { if (!eluac_ltr) {
String *metatable_tab = Getattr(nspace_hash, "metatable"); String *metatable_tab = Getattr(carrays_hash, "metatable");
assert(metatable_tab); assert(metatable_tab);
if (elua_ltr) { if (elua_ltr) {
String *get_tab_name = Getattr(nspace_hash, "get:name"); String *get_tab_name = Getattr(carrays_hash, "get:name");
String *set_tab_name = Getattr(nspace_hash, "set:name"); String *set_tab_name = Getattr(carrays_hash, "set:name");
if (Getattr(nspace_hash, "lua:class_instance")) { if (Getattr(carrays_hash, "lua:class_instance")) {
Printv(metatable_tab, tab4, "{LSTRKEY(\"__index\"), LFUNCVAL(SWIG_Lua_class_get)},\n", NIL); 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); Printv(metatable_tab, tab4, "{LSTRKEY(\"__newindex\"), LFUNCVAL(SWIG_Lua_class_set)},\n", NIL);
} else { } else {
@ -1926,10 +1938,10 @@ public:
Printv(metatable_tab, tab4, "{LSTRKEY(\"__gc\"), LFUNCVAL(SWIG_Lua_class_destruct)},\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(\".get\"), LROVAL(", get_tab_name, ")},\n", NIL);
Printv(metatable_tab, tab4, "{LSTRKEY(\".set\"), LROVAL(", set_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); Printv(metatable_tab, tab4, "{LSTRKEY(\".fn\"), LROVAL(", Getattr(carrays_hash, "methods:name"), ")},\n", NIL);
if (Getattr(nspace_hash, "lua:class_instance")) { if (Getattr(carrays_hash, "lua:class_instance")) {
String *static_cls = Getattr(nspace_hash, "lua:class_instance:static_hash"); String *static_cls = Getattr(carrays_hash, "lua:class_instance:static_hash");
assert(static_cls); assert(static_cls);
// static_cls is swig_lua_namespace. This structure can't be use with eLua(LTR) // static_cls is swig_lua_namespace. This structure can't be use with eLua(LTR)
// Instead structure describing its methods isused // Instead structure describing its methods isused
@ -1938,8 +1950,8 @@ public:
Printv(metatable_tab, tab4, "{LSTRKEY(\".static\"), LROVAL(", static_cls_cname, ")},\n", NIL); Printv(metatable_tab, tab4, "{LSTRKEY(\".static\"), LROVAL(", static_cls_cname, ")},\n", NIL);
// Put forward declaration of this array // Put forward declaration of this array
Printv(output, "extern ", Getattr(static_cls, "methods:decl"), "\n", NIL); Printv(output, "extern ", Getattr(static_cls, "methods:decl"), "\n", NIL);
} else if (Getattr(nspace_hash, "lua:class_static")) { } else if (Getattr(carrays_hash, "lua:class_static")) {
Hash *instance_cls = Getattr(nspace_hash, "lua:class_static:instance_hash"); Hash *instance_cls = Getattr(carrays_hash, "lua:class_static:instance_hash");
assert(instance_cls); assert(instance_cls);
String *instance_cls_metatable_name = Getattr(instance_cls, "metatable:name"); String *instance_cls_metatable_name = Getattr(instance_cls, "metatable:name");
assert(instance_cls_metatable_name); assert(instance_cls_metatable_name);
@ -1962,42 +1974,53 @@ public:
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* closeNamespaceHash() * closeCArraysHash()
* Recursively close all non-closed namespaces. Prints data to dataOutput. * Recursively close all non-closed namespaces. Prints data to dataOutput.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
void closeNamespaces(File *dataOutput) { void closeNamespaces(File *dataOutput) {
// Special handling for empty module. // Special handling for empty module.
if (Getattr(namespaces_hash, "") == 0) { if (scopeLookup("") == 0 || rawGetCArraysHash("") == 0) {
// Module is empty. Create hash for global scope in order to have swig__Module // Module is empty. Create hash for global scope in order to have swig__Module
// variable in resulting file // variable in resulting file
getNamespaceHash(0); getCArraysHash(0);
} }
Iterator ki = First(namespaces_hash); // Because we cant access directly 'symtabs', instead we access
// top-level scope and look on all scope pseudo-symbols in it.
Hash *top_scope = scopeLookup("");
assert(top_scope);
Iterator ki = First(top_scope);
List *to_close = NewList(); List *to_close = NewList();
while (ki.key) { while (ki.key) {
if (Getattr(ki.item, "lua:closed") == 0) assert(ki.item);
Append(to_close, ki.key); if (Getattr(ki.item, "sym:is_scope")) {
// We have a pseudo symbol. Lets get actuall scope for this
// pseudo symbol
Hash *carrays_hash = rawGetCArraysHash(ki.key);
assert(carrays_hash);
if (Getattr(carrays_hash, "lua:closed") == 0)
Append(to_close, ki.key);
}
ki = Next(ki); ki = Next(ki);
} }
SortList(to_close, &compareByLen); SortList(to_close, &compareByLen);
int len = Len(to_close); int len = Len(to_close);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
String *key = Getitem(to_close, i); String *key = Getitem(to_close, i);
closeNamespaceHash(key, dataOutput); closeCArraysHash(key, dataOutput);
Hash *nspace = Getattr(namespaces_hash, key); Hash *carrays_hash = rawGetCArraysHash(key);
String *name = 0; // name - name of the namespace as it should be visible in Lua String *name = 0; // name - name of the namespace as it should be visible in Lua
if (DohLen(key) == 0) // This is global module if (DohLen(key) == 0) // This is global module
name = module; name = module;
else else
name = Getattr(nspace, "name"); name = Getattr(carrays_hash, "name");
assert(name); assert(name);
printNamespaceDefinition(key, name, dataOutput); printCArraysDefinition(key, name, dataOutput);
} }
Delete(to_close); Delete(to_close);
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* printNamespaceDefinition() * printCArraysDefinition()
* This function prints to output a definition of namespace in * This function prints to output a definition of namespace in
* form * form
* swig_lua_namespace $cname = { attr_array, methods_array, ... , namespaces_array }; * swig_lua_namespace $cname = { attr_array, methods_array, ... , namespaces_array };
@ -2005,21 +2028,21 @@ public:
* 'name' is a user-visible name that this namespace will have in Lua. It shouldn't * 'name' is a user-visible name that this namespace will have in Lua. It shouldn't
* be fully qualified name, just it's own name. * be fully qualified name, just it's own name.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
void printNamespaceDefinition(String *nspace, String *name, File *output) { void printCArraysDefinition(String *nspace, String *name, File *output) {
Hash *nspace_hash = getNamespaceHash(nspace, false); Hash *carrays_hash = getCArraysHash(nspace, false);
String *cname = Getattr(nspace_hash, "cname"); // cname - name of the C structure that describes namespace String *cname = Getattr(carrays_hash, "cname"); // cname - name of the C structure that describes namespace
assert(cname); assert(cname);
Printv(output, "static swig_lua_namespace ", cname, " = ", NIL); Printv(output, "static swig_lua_namespace ", cname, " = ", NIL);
String *null_string = NewString("0"); String *null_string = NewString("0");
String *attr_tab_name = Getattr(nspace_hash, "attributes:name"); String *attr_tab_name = Getattr(carrays_hash, "attributes:name");
String *methods_tab_name = Getattr(nspace_hash, "methods:name"); String *methods_tab_name = Getattr(carrays_hash, "methods:name");
String *const_tab_name = Getattr(nspace_hash, "constants:name"); String *const_tab_name = Getattr(carrays_hash, "constants:name");
String *classes_tab_name = Getattr(nspace_hash, "classes:name"); String *classes_tab_name = Getattr(carrays_hash, "classes:name");
String *namespaces_tab_name = Getattr(nspace_hash, "namespaces:name"); String *namespaces_tab_name = Getattr(carrays_hash, "namespaces:name");
bool has_classes = Getattr(nspace_hash, "lua:no_classes") == 0; bool has_classes = Getattr(carrays_hash, "lua:no_classes") == 0;
bool has_namespaces = Getattr(nspace_hash, "lua:no_namespaces") == 0; bool has_namespaces = Getattr(carrays_hash, "lua:no_namespaces") == 0;
Printv(output, "{\n", Printv(output, "{\n",
tab4, "\"", name, "\",\n", tab4, "\"", name, "\",\n",
@ -2064,15 +2087,12 @@ public:
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* luaAddSymbol() * luaAddSymbol()
* Our implementation of addSymbol. Determines scope correctly, then calls Language::addSymbol * Our implementation of addSymbol. Determines scope correctly, then
* forwards to Language::addSymbol
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
int luaAddSymbol(const String *s, const Node *n) { int luaAddSymbol(const String *s, const Node *n) {
String *scope = luaCurrentSymbolNSpace(); String *scope = luaCurrentSymbolNSpace();
//Printf(stdout, "luaAddSymbol: %s scope: %s\n", s, scope); return luaAddSymbol(s, n, scope);
int result = Language::addSymbol(s, n, scope);
if (!result)
Printf(stderr, "addSymbol(%s to scope %s) failed\n", s, scope);
return result;
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
@ -2080,7 +2100,6 @@ public:
* Overload. Enforces given scope. Actually, it simply forwards call to Language::addSymbol * 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) { int luaAddSymbol(const String *s, const Node *n, const_String_or_char_ptr scope) {
//Printf(stdout, "luaAddSymbol: %s scope: %s\n", s, scope);
int result = Language::addSymbol(s, n, scope); int result = Language::addSymbol(s, n, scope);
if (!result) if (!result)
Printf(stderr, "addSymbol(%s to scope %s) failed\n", s, scope); Printf(stderr, "addSymbol(%s to scope %s) failed\n", s, scope);

View file

@ -215,7 +215,10 @@ public:
virtual int validIdentifier(String *s); /* valid identifier? */ virtual int validIdentifier(String *s); /* valid identifier? */
virtual int addSymbol(const String *s, const Node *n, const_String_or_char_ptr scope = ""); /* Add symbol */ virtual int addSymbol(const String *s, const Node *n, const_String_or_char_ptr scope = ""); /* Add symbol */
virtual void dumpSymbols(); virtual void dumpSymbols();
virtual Node *symbolLookup(String *s, const_String_or_char_ptr scope = ""); /* Symbol lookup */ virtual Node *symbolLookup(String *s, const_String_or_char_ptr scope = ""); /* Symbol lookup */
virtual Hash* addScope(const_String_or_char_ptr scope);
virtual Hash* scopeLookup( const_String_or_char_ptr scope );
virtual Hash* scopeSymbolLookup( const_String_or_char_ptr scope );
virtual Node *classLookup(const SwigType *s) const; /* Class lookup */ virtual Node *classLookup(const SwigType *s) const; /* Class lookup */
virtual Node *enumLookup(SwigType *s); /* Enum lookup */ virtual Node *enumLookup(SwigType *s); /* Enum lookup */
virtual int abstractClassTest(Node *n); /* Is class really abstract? */ virtual int abstractClassTest(Node *n); /* Is class really abstract? */