bool HybridBase::getMethod(const char *name) const { SLB_DEBUG_CALL; if (_L == 0) throw std::runtime_error("Hybrid instance not attached");\ SLB_DEBUG_STACK(5,_L, "HybridBase(%p)::getMethod '%s' (_L = %p)", this, name, _L); int top = lua_gettop(_L); // first try to find in _subclassMethods if (_subclassMethods.valid()) { //TODO: NEED DEBUG... // ---- why not: // Object *m = obj->_subclassMethods->get(key); // if (m) // { // SLB_DEBUG(5, "Hybrid subclassed instance, looking for '%s' method [OK]", key); // m->push(L); // return 1; // } // else SLB_DEBUG(5, "Hybrid subclassed instance, looking for '%s' method [FAIL!]", key); // ---- instead of: (even though this is quicker) but code above should work lua_pushstring(_L,name); // [+1] _subclassMethods->getCache(_L); // [-1, +1] will pop key's copy and return the cache if (!lua_isnil(_L,-1)) { assert("Invalid Stack" && (lua_gettop(_L) == top+1)); return true; } lua_pop(_L,1); // [-1] remove nil assert("Invalid Stack" && (lua_gettop(_L) == top)); //end TODO------------------------------------------------------------------------------- } ClassInfo *ci = getClassInfo(); ci->push(_L); lua_getmetatable(_L,-1); lua_getfield(_L,-1, "__hybrid"); if (!lua_isnil(_L,-1)) { lua_pushstring(_L,name); lua_rawget(_L,-2); if (!lua_isnil(_L,-1)) { lua_replace(_L,top+1); lua_settop(_L,top+1); SLB_DEBUG(6, "HybridBase(%p-%s)::getMethod '%s' (_L = %p) -> FOUND", this, ci->getName().c_str(),name, _L); assert("Invalid Stack" && (lua_gettop(_L) == top+1)); return true; } else SLB_DEBUG(6, "HybridBase(%p-%s)::getMethod '%s' (_L = %p) -> *NOT* FOUND", this,ci->getName().c_str(), name, _L); } else SLB_DEBUG(4, "HybridBase(%p-%s) do not have any hybrid methods", this, ci->getName().c_str()); // anyway... if not found: lua_settop(_L,top); return false; }
int HybridBase::class__index(lua_State *L) { SLB_DEBUG_CALL; SLB_DEBUG_CLEAN_STACK(L,+1); SLB_DEBUG_STACK(6, L, "Call class__index"); // trying to traverse the class... create a new InternalHybridSubclass ClassInfo *ci = Manager::getInstance().getClass(L,1); if (ci == 0) luaL_error(L, "Expected a valid class."); luaL_checkstring(L,2); // only valid with strings if (!ci->hasConstructor()) { luaL_error(L, "Hybrid Class(%s) doesn't have constructor." " You can not subclass(%s) from it", ci->getName().c_str(), lua_tostring(L,2)); } ref_ptr<InternalHybridSubclass> subc = new InternalHybridSubclass(ci); subc->push(L); // -- set cache... lua_pushvalue(L,2); // [+1] key lua_pushvalue(L,-2); // [+1] copy of new InternalHybrid... ci->setCache(L); // [-2] keep a copy in the cache // -- set cache done return 1; }
const HybridBase* get_hybrid(lua_State *L, int pos) { SLB_DEBUG_CALL; //TODO: Generalize this to be used in all SLB const HybridBase *obj = get<const HybridBase*>(L,pos); if (!obj) { if (lua_type(L,pos) == LUA_TUSERDATA) { void *dir = lua_touserdata(L,pos); // try to get the class info: ClassInfo *ci = Manager::getInstance().getClass(L,pos); if (ci == 0) { luaL_error(L, "Invalid Hybrid object (index=%d) " "'%s' %p", pos, ci->getName().c_str(), dir); } else { luaL_error(L, "Invalid Hybrid object (index=%d) " "userdata (NOT REGISTERED WITH SLB) %p", pos, dir); } } else { luaL_error(L, "Invalid Hybrid object (index=%d) found %s", pos, luaL_typename(L,pos)); } } return obj; }
/*--- Invalid Method (exception) ----------------------------------------------*/ InvalidMethod::InvalidMethod(const HybridBase *obj, const char *c) { SLB_DEBUG_CALL; lua_State *L = obj->getLuaState(); const ClassInfo *CI = obj->getClassInfo(); std::ostringstream out; lua_Debug debug; out << "Invalid Method '" << CI->getName() << "::" << c << "' NOT FOUND!" << std::endl; out << "TraceBack:" << std::endl; for ( int level = 0; lua_getstack(L, level, &debug ); level++) { if (lua_getinfo(L, "Sln", &debug) ) { //TODO use debug.name and debug.namewhat //make this more friendly out << "\t [ " << level << " (" << debug.what << ") ] "; if (debug.currentline > 0 ) { out << debug.short_src << ":" << debug.currentline; if (debug.name) out << " @ " << debug.name << "(" << debug.namewhat << ")"; } out << std::endl; } else { out << "[ERROR using Lua DEBUG INTERFACE]" << std::endl; } } out << "Current Stack:" << std::endl; for(int i = 1; i < lua_gettop(L); ++i) { out << "\t ["<<i<<"] " << lua_typename(L, lua_type(L,i)) << " : "<< lua_tostring(L,i) ; ClassInfo *ci = Manager::getInstance().getClass(L,i); if (ci) out << "->" << ci->getName(); out << std::endl; } _what = out.str(); }