diff options
Diffstat (limited to 'Source/external/Luax/luax_class.cpp')
-rw-r--r-- | Source/external/Luax/luax_class.cpp | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/Source/external/Luax/luax_class.cpp b/Source/external/Luax/luax_class.cpp new file mode 100644 index 0000000..762f0dc --- /dev/null +++ b/Source/external/Luax/luax_class.cpp @@ -0,0 +1,243 @@ +#include "luax_class.hpp" +#include "luax_cfunctions.h" +#include "luax_vm.h" + +namespace Luax +{ + +#if LUAX_ENABLE_PLAIN_CLASS + + int LuaxPlainClass::registry(lua_State* L) + { + LUAX_STATE(L); + + // params: + // 1: class name + + cc8* type = state.GetValue<cc8*>(1, ""); + + lua_newtable(L); // class table + + // GetClassName() + lua_pushstring(L, type); + lua_pushcclosure(L, luax_c_getupvalue, 1); + lua_setfield(L, -2, "GetClassName"); + + // GetClass() + lua_pushvalue(L, -1); // class table + lua_pushcclosure(L, luax_c_getupvalue, 1); + lua_setfield(L, -2, "GetClass"); + + // TypeOf() + lua_pushcfunction(L, _TypeOf); + lua_setfield(L, -2, "TypeOf"); + + // New() + lua_pushvalue(L, -1); // class table + lua_pushcclosure(L, _New, 1); + lua_setfield(L, -2, "New"); + + // Extend() + lua_pushvalue(L, -1); // class table + lua_pushcclosure(L, _Extend, 1); + lua_setfield(L, -2, "Extend"); + + lua_pushvalue(L, -1); // class table + lua_setfield(L, -2, "__index"); + + lua_pushstring(L, type); + lua_pushcclosure(L, __tostring, 1); + lua_setfield(L, -2, "__tostring"); + + return 1; + } + + int LuaxPlainClass::__tostring(lua_State* L) + { + // upvalues: + // 1: class name + + // params: + // 1: instance + + if (!lua_istable(L, 1)) + { + return luaL_typerror(L, 1, lua_typename(L, LUA_TTABLE)); + } + + cc8* type = lua_tostring(L, lua_upvalueindex(1)); + + lua_pushfstring(L, "%s: %p", type, lua_topointer(L, 1)); + + return 1; + } + + /// + /// NewnԻȡ__init__initʼʵ + /// + int LuaxPlainClass::_New(lua_State* L) + { + LUAX_STATE(L); + + // upvalues: + // 1: class table + + // params: + // n: params + int n = lua_gettop(L); + + int classTable = lua_upvalueindex(1); + + lua_newtable(L); // instance table + + // instance metatable Ϊ class + lua_pushvalue(L, classTable); + lua_setmetatable(L, -2); + + // ҵ캯ᴥmetatable.__index,ݼ̳ҡ + lua_getfield(L, classTable, "__init"); + if (state.IsType(-1, LUA_TFUNCTION)) + { + // stack: + // -1: __init() + // -2: instance + // -3~-n-2: params + + lua_insert(L, -2 - n); + // stack: + // -1: instance + // -2~-n-1: params + // -n-2: __init() + + lua_pushvalue(L, -1); + // stack: + // -1: instance + // -2: instance + // -3~-n-2: params + // -n-3: __init + + lua_insert(L, -3 - n); + // stack: + // -1: instance + // -2~-n-1: params + // -n-2: __init() + // -n-3: instance + + lua_insert(L, -1 - n); + // stack: + // -1~-n: params + // -n-1: instance + // -n-2: __init() + // -n-3: instance + + lua_pcall(L, n + 1, 0, 0); + } + else + { + state.Pop(); + } + + return 1; + } + + int LuaxPlainClass::_Extend(lua_State* L) + { + LUAX_STATE(L); + + // upvalues: + // 1: base class + + // params: + // 1: class name + + cc8* type = state.GetValue<cc8*>(1, ""); + + int baseClass = lua_upvalueindex(1); + + lua_newtable(L); // class table + + // GetClassName() + lua_pushstring(L, type); + lua_pushcclosure(L, luax_c_getupvalue, 1); + lua_setfield(L, -2, "GetClassName"); + + // GetClass() + lua_pushvalue(L, -1); // class table + lua_pushcclosure(L, luax_c_getupvalue, 1); + lua_setfield(L, -2, "GetClass"); + + // New() + lua_pushvalue(L, -1); // class table + lua_pushcclosure(L, _New, 1); + lua_setfield(L, -2, "New"); + + // Extend() + lua_pushvalue(L, -1); // class table + lua_pushcclosure(L, _Extend, 1); + lua_setfield(L, -2, "Extend"); + + // .__base + lua_pushvalue(L, baseClass); // base class + lua_setfield(L, -2, "__base"); + + lua_pushvalue(L, -1); // class table + lua_setfield(L, -2, "__index"); + + lua_pushstring(L, type); + lua_pushcclosure(L, __tostring, 1); + lua_setfield(L, -2, "__tostring"); + + // classmetatableΪbaseClass + lua_pushvalue(L, baseClass); + lua_setmetatable(L, -2); + + return 1; + } + + int LuaxPlainClass::_TypeOf(lua_State* L) + { + // params: + // 1: lua instance + // 2: type string + + LUAX_STATE(L); + + cc8* type = state.GetValue<cc8*>(2, ""); + + if (!lua_istable(L, 1)) + { + return luaL_typerror(L, 1, "Object"); + } + + lua_pushvalue(L, 1); // lua instance + + while (lua_getmetatable(L, -1)) + { + lua_getfield(L, -1, "GetClassName"); + if (lua_isfunction(L, -1)) + { + state.Call(0, 1); + cc8* name = state.GetValue<cc8*>(-1, ""); + if (strcmp(name, type) == 0) + { + lua_pushboolean(L, true); + return 1; + } + else + { + state.Pop(); // name + } + } + else + { + state.Pop(); + } + } + + lua_pushboolean(L, false); + return 1; + } + +#endif /*LUAX_ENABLE_PLAIN_CLASS*/ + +}
\ No newline at end of file |