twnlua: use stb_ds.h for enum conversions

This commit is contained in:
veclavtalica 2024-12-24 10:03:19 +03:00
parent e06c879869
commit 190eb1f107
2 changed files with 28 additions and 9 deletions

View File

@ -32,11 +32,13 @@ def default(parameter):
print('#include "twn_game_api.h"\n') print('#include "twn_game_api.h"\n')
print('#define STB_DS_IMPLEMENTATION') # TODO: reuse implementation from the engine
print('#include <stb_ds.h>')
print('#include <lua.h>') print('#include <lua.h>')
print('#include <lualib.h>') print('#include <lualib.h>')
print('#include <lauxlib.h>\n') print('#include <lauxlib.h>\n')
print('#include <string.h>\n')
storages, converters, initializers, deinitializers = [], [], [], []
for typename, typedesc in api["types"].items(): for typename, typedesc in api["types"].items():
converter = "static %s to_%s(lua_State *L, int idx) {\n" % (typename, typename.lower()) 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"])) raise BaseException("Unhandled converter field type '%s'" % (field["type"]))
converter += " lua_pop(L, 1);\n"; converter += " lua_pop(L, 1);\n";
# todo: use a hashtable instead # TODO: wild idea: use compile time built hash table
elif "enums" in typedesc: 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"; converter += " char *value = lua_tostring(L, -1);\n";
for index, enum in enumerate(typedesc["enums"]): converter += " %s = shget(%s_map, value);\n" % (typename.lower(), typename.lower())
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 += " lua_pop(L, 1);\n"; converter += " lua_pop(L, 1);\n";
converter += " return %s;\n}\n" % (typename.lower()) 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(): for procedure, procedure_desc in api["procedures"].items():
binding = "static int binding_%s(lua_State *L) {\n" % procedure binding = "static int binding_%s(lua_State *L) {\n" % procedure
binding += " luaL_checktype(L, 1, LUA_TTABLE);\n" 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"] loader = "void bindgen_load_%s(lua_State *L) {\n" % api["name"]
modules = set(api["procedures"][procedure]["module"] for procedure in api["procedures"]) modules = set(api["procedures"][procedure]["module"] for procedure in api["procedures"])
for module in modules: for module in modules:
loader += " bindgen_init();\n"
loader += " lua_newtable(L);\n" loader += " lua_newtable(L);\n"
for procedure, procedure_desc in api["procedures"].items(): for procedure, procedure_desc in api["procedures"].items():
if procedure_desc["module"] == module: if procedure_desc["module"] == module:
@ -128,3 +139,9 @@ for module in modules:
loader += "}" loader += "}"
print(loader) print(loader)
unloader = "void bindgen_unload_%s(lua_State *L) {\n" % api["name"]
unloader += '\n'.join(deinitializers)
unloader += "}"
print(unloader)

View File

@ -12,6 +12,7 @@
/* generated by bindgen.py */ /* generated by bindgen.py */
void bindgen_load_twn(lua_State *L); 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 */ /* 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) { void game_end(void) {
State *state = ctx.udata; State *state = ctx.udata;
bindgen_unload_twn(state->L);
lua_close(state->L); lua_close(state->L);
free(state); free(state);
} }