summaryrefslogtreecommitdiff
path: root/Source/external/Luax/luax_class.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/external/Luax/luax_class.cpp')
-rw-r--r--Source/external/Luax/luax_class.cpp243
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