Skip to content

Commit

Permalink
AP_Scripting: move singleton method bindings to flash
Browse files Browse the repository at this point in the history
  • Loading branch information
IamPete1 committed Jan 27, 2022
1 parent da79a5e commit 68a3df8
Showing 1 changed file with 132 additions and 75 deletions.
207 changes: 132 additions & 75 deletions libraries/AP_Scripting/generator/src/main.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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");
Expand All @@ -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");
Expand All @@ -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");

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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();
Expand All @@ -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();

Expand Down

0 comments on commit 68a3df8

Please sign in to comment.