diff --git a/libraries/AP_Scripting/generator/src/main.c b/libraries/AP_Scripting/generator/src/main.c index 2f0bad01b98d7..619c468ea003b 100644 --- a/libraries/AP_Scripting/generator/src/main.c +++ b/libraries/AP_Scripting/generator/src/main.c @@ -1944,7 +1944,7 @@ void emit_operators(struct userdata *data) { } } -void emit_userdata_methods(struct userdata *node) { +void emit_methods(struct userdata *node) { while(node) { // methods struct method *method = node->methods; @@ -1995,10 +1995,22 @@ void emit_userdata_metatables(void) { } } -void emit_singleton_metatables(struct userdata *head) { +void emit_enum(struct userdata * data) { + fprintf(source, "struct userdata_enum %s_enums[] = {\n", data->sanatized_name); + struct userdata_enum *ud_enum = data->enums; + while (ud_enum != NULL) { + fprintf(source, " {\"%s\", %s::%s},\n", ud_enum->name, data->name, ud_enum->name); + ud_enum = ud_enum->next; + } + fprintf(source, "};\n\n"); +} + +void emit_index(struct userdata *head) { + struct userdata * node = head; while(node) { start_dependency(source, node->dependency); + fprintf(source, "const luaL_Reg %s_meta[] = {\n", node->sanatized_name); struct method *method = node->methods; @@ -2013,41 +2025,61 @@ void emit_singleton_metatables(struct userdata *head) { field = field->next; } - fprintf(source, " {NULL, NULL}\n"); - fprintf(source, "};\n"); + fprintf(source, "};\n\n"); + + if (node->operations) { + fprintf(source, "const luaL_Reg %s_operators[] = {\n", node->sanatized_name); + for (uint32_t i = 1; i < OP_LAST; i = (i << 1)) { + const char * op_name = get_name_for_operation((node->operations) & i); + if (op_name == NULL) { + continue; + } + fprintf(source, " {\"%s\", %s_%s},\n", op_name, node->sanatized_name, op_name); + } + fprintf(source, " {NULL, NULL},\n"); + fprintf(source, "};\n\n"); + } + + if (node->enums != NULL) { + emit_enum(node); + } + + fprintf(source, "static int %s_index(lua_State *L) {\n", node->sanatized_name); + fprintf(source, " const char * name = luaL_checkstring(L, 2);\n"); + fprintf(source, " if (load_function(L,%s_meta,ARRAY_SIZE(%s_meta),name)",node->sanatized_name,node->sanatized_name); + if (node->enums != NULL) { + fprintf(source, " || load_enum(L,%s_enums,ARRAY_SIZE(%s_enums),name)",node->sanatized_name,node->sanatized_name); + } + fprintf(source, ") {\n"); + fprintf(source, " return 1;\n"); + fprintf(source, " }\n"); + fprintf(source, " return 0;\n"); + fprintf(source, "}\n"); end_dependency(source, node->dependency); fprintf(source, "\n"); - node = node->next; } } -void emit_enums(struct userdata * data) { +void emit_type_index(struct userdata * data, char * meta_name) { + fprintf(source, "const struct luaL_Reg %s_fun[] = {\n", meta_name); while (data) { - if (data->enums != NULL) { - start_dependency(source, data->dependency); - fprintf(source, "struct userdata_enum %s_enums[] = {\n", data->sanatized_name); - struct userdata_enum *ud_enum = data->enums; - while (ud_enum != NULL) { - fprintf(source, " {\"%s\", %s::%s},\n", ud_enum->name, data->name, ud_enum->name); - ud_enum = ud_enum->next; - } - fprintf(source, " {NULL, 0}};\n"); - end_dependency(source, data->dependency); - fprintf(source, "\n"); - } + start_dependency(source, data->dependency); + fprintf(source, " {\"%s\", %s_index},\n", data->alias ? data->alias : data->name, data->sanatized_name); + end_dependency(source, data->dependency); data = data->next; } + fprintf(source, "};\n\n"); } -void emit_metas(struct userdata * data, char * meta_name) { +void emit_type_index_with_operators(struct userdata * data, char * meta_name) { fprintf(source, "const struct userdata_meta %s_fun[] = {\n", meta_name); while (data) { start_dependency(source, data->dependency); - if (data->enums) { - fprintf(source, " {\"%s\", %s_meta, %s_enums},\n", data->alias ? data->alias : data->name, data->name, data->sanatized_name); + if (data->operations == 0) { + fprintf(source, " {\"%s\", %s_index, nullptr},\n", data->alias ? data->alias : data->name, data->sanatized_name); } else { - fprintf(source, " {\"%s\", %s_meta, NULL},\n", data->alias ? data->alias : data->name, data->sanatized_name); + fprintf(source, " {\"%s\", %s_index, %s_operators},\n", data->alias ? data->alias : data->name, data->sanatized_name, data->sanatized_name); } end_dependency(source, data->dependency); data = data->next; @@ -2056,66 +2088,61 @@ void emit_metas(struct userdata * data, char * meta_name) { } void emit_loaders(void) { - // emit the enum header - fprintf(source, "struct userdata_enum {\n"); - fprintf(source, " const char *name;\n"); - fprintf(source, " int value;\n"); - fprintf(source, "};\n\n"); - emit_enums(parsed_userdata); - emit_enums(parsed_singletons); - // emit the meta table header - fprintf(source, "struct userdata_meta {\n"); - fprintf(source, " const char *name;\n"); - fprintf(source, " const luaL_Reg *reg;\n"); - fprintf(source, " const struct userdata_enum *enums;\n"); - fprintf(source, "};\n\n"); - emit_metas(parsed_userdata, "userdata"); - emit_metas(parsed_singletons, "singleton"); - emit_metas(parsed_ap_objects, "ap_object"); + emit_type_index_with_operators(parsed_userdata, "userdata"); + emit_type_index(parsed_singletons, "singleton"); + emit_type_index(parsed_ap_objects, "ap_object"); fprintf(source, "void load_generated_bindings(lua_State *L) {\n"); fprintf(source, " luaL_checkstack(L, 5, \"Out of stack\");\n"); // this is more stack space then we need, but should never fail fprintf(source, " // userdata metatables\n"); fprintf(source, " for (uint32_t i = 0; i < ARRAY_SIZE(userdata_fun); i++) {\n"); fprintf(source, " luaL_newmetatable(L, userdata_fun[i].name);\n"); - fprintf(source, " luaL_setfuncs(L, userdata_fun[i].reg, 0);\n"); - fprintf(source, " lua_pushstring(L, \"__index\");\n"); + fprintf(source, " lua_pushcclosure(L, userdata_fun[i].func, 0);\n"); + fprintf(source, " lua_setfield(L, -2, \"__index\");\n"); + + fprintf(source, " if (userdata_fun[i].operators != nullptr) {\n"); + fprintf(source, " luaL_setfuncs(L, userdata_fun[i].operators, 0);\n"); + fprintf(source, " }\n"); + + fprintf(source, " lua_pushstring(L, \"__call\");\n"); fprintf(source, " lua_pushvalue(L, -2);\n"); fprintf(source, " lua_settable(L, -3);\n"); + fprintf(source, " lua_pop(L, 1);\n"); + fprintf(source, " lua_newuserdata(L, 0);\n"); + fprintf(source, " luaL_getmetatable(L, userdata_fun[i].name);\n"); + fprintf(source, " lua_setmetatable(L, -2);\n"); + fprintf(source, " lua_setglobal(L, userdata_fun[i].name);\n"); fprintf(source, " }\n"); fprintf(source, "\n"); fprintf(source, " // ap object metatables\n"); fprintf(source, " for (uint32_t i = 0; i < ARRAY_SIZE(ap_object_fun); i++) {\n"); fprintf(source, " luaL_newmetatable(L, ap_object_fun[i].name);\n"); - fprintf(source, " luaL_setfuncs(L, ap_object_fun[i].reg, 0);\n"); - fprintf(source, " lua_pushstring(L, \"__index\");\n"); + fprintf(source, " lua_pushcclosure(L, ap_object_fun[i].func, 0);\n"); + fprintf(source, " lua_setfield(L, -2, \"__index\");\n"); + fprintf(source, " lua_pushstring(L, \"__call\");\n"); fprintf(source, " lua_pushvalue(L, -2);\n"); fprintf(source, " lua_settable(L, -3);\n"); + fprintf(source, " lua_pop(L, 1);\n"); + fprintf(source, " lua_newuserdata(L, 0);\n"); + fprintf(source, " luaL_getmetatable(L, ap_object_fun[i].name);\n"); + fprintf(source, " lua_setmetatable(L, -2);\n"); + fprintf(source, " lua_setglobal(L, ap_object_fun[i].name);\n"); fprintf(source, " }\n"); fprintf(source, "\n"); fprintf(source, " // singleton metatables\n"); fprintf(source, " for (uint32_t i = 0; i < ARRAY_SIZE(singleton_fun); i++) {\n"); fprintf(source, " luaL_newmetatable(L, singleton_fun[i].name);\n"); - fprintf(source, " luaL_setfuncs(L, singleton_fun[i].reg, 0);\n"); - fprintf(source, " lua_pushstring(L, \"__index\");\n"); + fprintf(source, " lua_pushcclosure(L, singleton_fun[i].func, 0);\n"); + fprintf(source, " lua_setfield(L, -2, \"__index\");\n"); + fprintf(source, " lua_pushstring(L, \"__call\");\n"); fprintf(source, " lua_pushvalue(L, -2);\n"); fprintf(source, " lua_settable(L, -3);\n"); - fprintf(source, " if (singleton_fun[i].enums != nullptr) {\n"); - fprintf(source, " int j = 0;\n"); - fprintf(source, " while (singleton_fun[i].enums[j].name != NULL) {\n"); - fprintf(source, " lua_pushstring(L, singleton_fun[i].enums[j].name);\n"); - fprintf(source, " lua_pushinteger(L, singleton_fun[i].enums[j].value);\n"); - fprintf(source, " lua_settable(L, -3);\n"); - fprintf(source, " j++;\n"); - fprintf(source, " }\n"); - fprintf(source, " }\n"); - fprintf(source, " lua_pop(L, 1);\n"); fprintf(source, " lua_newuserdata(L, 0);\n"); fprintf(source, " luaL_getmetatable(L, singleton_fun[i].name);\n"); @@ -2130,16 +2157,6 @@ void emit_loaders(void) { } void emit_sandbox(void) { - struct userdata *single = parsed_singletons; - fprintf(source, "const char *singletons[] = {\n"); - while (single) { - start_dependency(source, single->dependency); - fprintf(source, " \"%s\",\n", single->alias ? single->alias : single->sanatized_name); - end_dependency(source, single->dependency); - single = single->next; - } - fprintf(source, "};\n\n"); - struct userdata *data = parsed_userdata; fprintf(source, "const struct userdata {\n"); fprintf(source, " const char *name;\n"); @@ -2162,9 +2179,9 @@ void emit_sandbox(void) { fprintf(source, "void load_generated_sandbox(lua_State *L) {\n"); // load the singletons - fprintf(source, " for (uint32_t i = 0; i < ARRAY_SIZE(singletons); i++) {\n"); - fprintf(source, " lua_pushstring(L, singletons[i]);\n"); - fprintf(source, " lua_getglobal(L, singletons[i]);\n"); + fprintf(source, " for (uint32_t i = 0; i < ARRAY_SIZE(singleton_fun); i++) {\n"); + fprintf(source, " lua_pushstring(L, singleton_fun[i].name);\n"); + fprintf(source, " lua_getglobal(L, singleton_fun[i].name);\n"); fprintf(source, " lua_settable(L, -3);\n"); fprintf(source, " }\n"); @@ -2379,6 +2396,43 @@ void emit_docs(struct userdata *node, int is_userdata, int emit_creation) { } +void emit_index_helpers(void) { + fprintf(source, "static bool load_function(lua_State *L, const luaL_Reg *list, const uint8_t length, const char* name) {\n"); + fprintf(source, " for (uint8_t i = 0; i < length; i++) {\n"); + fprintf(source, " if (strcmp(name,list[i].name) == 0) {\n"); + fprintf(source, " lua_pushcfunction(L, list[i].func);\n"); + fprintf(source, " return true;\n"); + fprintf(source, " }\n"); + fprintf(source, " }\n"); + fprintf(source, " return false;\n"); + fprintf(source, "}\n\n"); + + fprintf(source, "static bool load_enum(lua_State *L, const userdata_enum *list, const uint8_t length, const char* name) {\n"); + fprintf(source, " for (uint8_t i = 0; i < length; i++) {\n"); + fprintf(source, " if (strcmp(name,list[i].name) == 0) {\n"); + fprintf(source, " lua_pushinteger(L, list[i].value);\n"); + fprintf(source, " return true;\n"); + fprintf(source, " }\n"); + fprintf(source, " }\n"); + fprintf(source, " return false;\n"); + fprintf(source, "}\n\n"); +} + +void emit_structs(void) { + // emit the enum header + fprintf(source, "struct userdata_enum {\n"); + fprintf(source, " const char *name;\n"); + fprintf(source, " int value;\n"); + fprintf(source, "};\n\n"); + + // emit the meta table header + fprintf(source, "struct userdata_meta {\n"); + fprintf(source, " const char *name;\n"); + fprintf(source, " lua_CFunction func;\n"); + fprintf(source, " const luaL_Reg *operators;\n"); + fprintf(source, "};\n\n"); +} + char * output_path = NULL; char * docs_path = NULL; @@ -2476,6 +2530,10 @@ int main(int argc, char **argv) { emit_not_supported_helper(); + emit_structs(); + + emit_index_helpers(); + emit_userdata_allocators(); emit_userdata_checkers(); @@ -2484,21 +2542,20 @@ int main(int argc, char **argv) { emit_ap_object_checkers(); - emit_userdata_fields(); - - emit_userdata_methods(parsed_userdata); - emit_userdata_metatables(); emit_singleton_fields(); + emit_methods(parsed_singletons); + emit_index(parsed_singletons); - emit_userdata_methods(parsed_singletons); + emit_userdata_fields(); + emit_methods(parsed_userdata); + emit_index(parsed_userdata); - emit_singleton_metatables(parsed_singletons); - emit_userdata_methods(parsed_ap_objects); + emit_methods(parsed_ap_objects); + emit_index(parsed_ap_objects); - emit_singleton_metatables(parsed_ap_objects); emit_loaders();