From 190eb1f107768929543a6be04fd1c3a19911d209 Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Tue, 24 Dec 2024 10:03:19 +0300 Subject: [PATCH] twnlua: use stb_ds.h for enum conversions --- apps/twnlua/bindgen.py | 35 ++++++++++++++++++++++++++--------- apps/twnlua/game.c | 2 ++ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/apps/twnlua/bindgen.py b/apps/twnlua/bindgen.py index 1211fc1..bfafcf5 100755 --- a/apps/twnlua/bindgen.py +++ b/apps/twnlua/bindgen.py @@ -32,11 +32,13 @@ def default(parameter): print('#include "twn_game_api.h"\n') +print('#define STB_DS_IMPLEMENTATION') # TODO: reuse implementation from the engine +print('#include ') print('#include ') print('#include ') print('#include \n') -print('#include \n') +storages, converters, initializers, deinitializers = [], [], [], [] for typename, typedesc in api["types"].items(): converter = "static %s to_%s(lua_State *L, int idx) {\n" % (typename, typename.lower()) @@ -53,21 +55,29 @@ for typename, typedesc in api["types"].items(): raise BaseException("Unhandled converter field type '%s'" % (field["type"])) converter += " lua_pop(L, 1);\n"; - # todo: use a hashtable instead + # TODO: wild idea: use compile time built hash table elif "enums" in typedesc: + storages += ["struct %sHashItem { char *key; %s value; };\nstatic struct %sHashItem *%s_map = NULL;\n" % (typename, typename, typename, typename.lower())] + + # TODO: use arena + for enum in typedesc["enums"]: + initializer = " shput(%s_map, \"%s\", %s);" % (typename.lower(), enum, typedesc["enums"][enum]) + initializers += [initializer] + + deinitializers += [" shfree(%s_map);" % typename.lower()] + converter += " char *value = lua_tostring(L, -1);\n"; - for index, enum in enumerate(typedesc["enums"]): - if index == 0: - converter += " if (strncmp(\"%s\", value, sizeof(\"%s\")) == 0)\n" % (enum, enum) - else: - converter += " else if (strncmp(\"%s\", value, sizeof(\"%s\")) == 0)\n" % (enum, enum) - converter += " %s = %s;\n" % (typename.lower(), typedesc["enums"][enum]) + converter += " %s = shget(%s_map, value);\n" % (typename.lower(), typename.lower()) converter += " lua_pop(L, 1);\n"; converter += " return %s;\n}\n" % (typename.lower()) - print(converter) + converters += [converter] +print('\n'.join(storages)) +print("void bindgen_init(void) {\n" + '\n'.join(initializers) + "\n}\n") +print('\n'.join(converters)) +bindings = [] for procedure, procedure_desc in api["procedures"].items(): binding = "static int binding_%s(lua_State *L) {\n" % procedure binding += " luaL_checktype(L, 1, LUA_TTABLE);\n" @@ -118,6 +128,7 @@ for procedure, procedure_desc in api["procedures"].items(): loader = "void bindgen_load_%s(lua_State *L) {\n" % api["name"] modules = set(api["procedures"][procedure]["module"] for procedure in api["procedures"]) for module in modules: + loader += " bindgen_init();\n" loader += " lua_newtable(L);\n" for procedure, procedure_desc in api["procedures"].items(): if procedure_desc["module"] == module: @@ -128,3 +139,9 @@ for module in modules: loader += "}" print(loader) + + +unloader = "void bindgen_unload_%s(lua_State *L) {\n" % api["name"] +unloader += '\n'.join(deinitializers) +unloader += "}" +print(unloader) diff --git a/apps/twnlua/game.c b/apps/twnlua/game.c index 824436e..5da7dd4 100644 --- a/apps/twnlua/game.c +++ b/apps/twnlua/game.c @@ -12,6 +12,7 @@ /* generated by bindgen.py */ void bindgen_load_twn(lua_State *L); +void bindgen_unload_twn(lua_State *L); /* require will go through physicsfs exclusively so that scripts can be in the data dir */ @@ -119,6 +120,7 @@ void game_tick(void) { void game_end(void) { State *state = ctx.udata; + bindgen_unload_twn(state->L); lua_close(state->L); free(state); }