Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scripting: use generator to load manual bindings #20668

Merged
merged 4 commits into from May 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions libraries/AP_Scripting/generator/description/bindings.desc
Expand Up @@ -453,6 +453,8 @@ include AP_InertialSensor/AP_InertialSensor.h
singleton AP_InertialSensor rename ins
singleton AP_InertialSensor method get_temperature float uint8_t 0 INS_MAX_INSTANCES

singleton CAN manual get_device lua_get_CAN_device
singleton CAN depends HAL_MAX_CAN_PROTOCOL_DRIVERS

include AP_Scripting/AP_Scripting_CANSensor.h depends HAL_MAX_CAN_PROTOCOL_DRIVERS
include AP_HAL/AP_HAL.h
Expand Down Expand Up @@ -510,3 +512,14 @@ singleton AP_Follow method get_target_heading_deg boolean float'Null
include AC_AttitudeControl/AC_AttitudeControl.h depends APM_BUILD_TYPE(APM_BUILD_ArduPlane)||APM_BUILD_COPTER_OR_HELI
singleton AC_AttitudeControl depends APM_BUILD_TYPE(APM_BUILD_ArduPlane)||APM_BUILD_COPTER_OR_HELI
singleton AC_AttitudeControl method get_rpy_srate void float'Ref float'Ref float'Ref



singleton AP_Logger rename logger
singleton AP_Logger manual write AP_Logger_Write

singleton i2c manual get_device lua_get_i2c_device

global manual millis lua_millis
global manual micros lua_micros
global manual mission_receive lua_mission_receive
126 changes: 101 additions & 25 deletions libraries/AP_Scripting/generator/src/main.c
Expand Up @@ -27,6 +27,8 @@ char keyword_write[] = "write";
char keyword_literal[] = "literal";
char keyword_reference[] = "reference";
char keyword_deprecate[] = "deprecate";
char keyword_manual[] = "manual";
char keyword_global[] = "global";

// attributes (should include the leading ' )
char keyword_attr_enum[] = "'enum";
Expand Down Expand Up @@ -58,6 +60,7 @@ enum error_codes {
ERROR_SINGLETON = 7, // singletons
ERROR_DEPENDS = 8, // dependencies
ERROR_DOCS = 9, // Documentation
ERROR_GLOBALS = 10,
};

struct header {
Expand Down Expand Up @@ -326,6 +329,7 @@ enum userdata_type {
UD_USERDATA,
UD_SINGLETON,
UD_AP_OBJECT,
UD_GLOBAL,
};

struct argument {
Expand All @@ -352,6 +356,7 @@ struct method_alias {
char *name;
char *alias;
int line;
int is_manual;
};

struct userdata_field {
Expand Down Expand Up @@ -394,6 +399,7 @@ struct userdata {

static struct userdata *parsed_userdata;
static struct userdata *parsed_ap_objects;
static struct userdata *parsed_globals;

void sanitize_character(char **str, char character) {
char *position = strchr(*str, character);
Expand Down Expand Up @@ -819,6 +825,24 @@ void handle_method(struct userdata *node) {
}
}

void handle_manual(struct userdata *node) {
char *name = next_token();
if (name == NULL) {
error(ERROR_SINGLETON, "Expected a lua name for manual %s method",node->name);
}
char *cpp_function_name = next_token();
if (cpp_function_name == NULL) {
error(ERROR_SINGLETON, "Expected a cpp name for manual %s method",node->name);
}
struct method_alias *alias = allocate(sizeof(struct method_alias));
string_copy(&(alias->name), cpp_function_name);
string_copy(&(alias->alias), name);
alias->line = state.line_num;
alias->is_manual = 1;
alias->next = node->method_aliases;
node->method_aliases = alias;
}

void handle_operator(struct userdata *data) {
trace(TRACE_USERDATA, "Adding a operator");

Expand Down Expand Up @@ -989,8 +1013,10 @@ void handle_singleton(void) {
handle_userdata_field(node);
} else if (strcmp(type, keyword_reference) == 0) {
node->flags |= UD_FLAG_REFERENCE;
} else if (strcmp(type, keyword_manual) == 0) {
handle_manual(node);
} else {
error(ERROR_SINGLETON, "Singletons only support renames, methods, semaphore, depends or literal keywords (got %s)", type);
error(ERROR_SINGLETON, "Singletons only support renames, methods, semaphore, depends, literal or manual keywords (got %s)", type);
}

// ensure no more tokens on the line
Expand Down Expand Up @@ -1076,6 +1102,31 @@ void handle_ap_object(void) {
}
}

void handle_global(void) {

if (parsed_globals == NULL) {
parsed_globals = (struct userdata *)allocate(sizeof(struct userdata));
parsed_globals->ud_type = UD_GLOBAL;
}

// read type
char *type = next_token();
if (type == NULL) {
error(ERROR_GLOBALS, "Expected a access type for global");
}

if (strcmp(type, keyword_manual) == 0) {
handle_manual(parsed_globals);
} else {
error(ERROR_GLOBALS, "globals only support manual keyword (got %s)", type);
}

// ensure no more tokens on the line
if (next_token()) {
error(ERROR_GLOBALS, "global contained an unexpected extra token: %s", state.token);
}
}

void sanity_check_userdata(void) {
struct userdata * node = parsed_userdata;
while(node) {
Expand Down Expand Up @@ -1496,10 +1547,12 @@ void emit_userdata_fields() {
struct userdata * node = parsed_userdata;
while(node) {
struct userdata_field *field = node->fields;
start_dependency(source, node->dependency);
while(field) {
emit_userdata_field(node, field);
field = field->next;
if (field) {
start_dependency(source, node->dependency);
while(field) {
emit_userdata_field(node, field);
field = field->next;
}
}
end_dependency(source, node->dependency);
node = node->next;
Expand Down Expand Up @@ -1594,12 +1647,14 @@ void emit_singleton_fields() {
struct userdata * node = parsed_singletons;
while(node) {
struct userdata_field *field = node->fields;
start_dependency(source, node->dependency);
while(field) {
emit_singleton_field(node, field);
field = field->next;
if (field) {
start_dependency(source, node->dependency);
while(field) {
emit_singleton_field(node, field);
field = field->next;
}
end_dependency(source, node->dependency);
}
end_dependency(source, node->dependency);
node = node->next;
}
}
Expand Down Expand Up @@ -1700,6 +1755,7 @@ void emit_userdata_method(const struct userdata *data, const struct method *meth
fprintf(source, " %s * ud = check_%s(L, 1);\n", data->name, data->sanatized_name);
break;
case UD_SINGLETON:
case UD_GLOBAL:
// this was bound early
break;
case UD_AP_OBJECT:
Expand Down Expand Up @@ -2086,7 +2142,11 @@ void emit_index(struct userdata *head) {

struct method_alias *alias = node->method_aliases;
while(alias) {
fprintf(source, " {\"%s\", %s_%s},\n", alias->alias, node->sanatized_name, alias->name);
if (alias->is_manual) {
fprintf(source, " {\"%s\", %s},\n", alias->alias, alias->name);
} else {
fprintf(source, " {\"%s\", %s_%s},\n", alias->alias, node->sanatized_name, alias->name);
}
alias = alias->next;
}

Expand Down Expand Up @@ -2240,6 +2300,16 @@ void emit_sandbox(void) {
end_dependency(source, data->dependency);
data = data->next;
}
if (parsed_globals) {
struct method_alias *manual_aliases = parsed_globals->method_aliases;
while (manual_aliases) {
if (manual_aliases->is_manual == 0) {
error(ERROR_GLOBALS, "Globals only support manual methods");
}
fprintf(source, " {\"%s\", %s},\n", manual_aliases->alias, manual_aliases->name);
manual_aliases = manual_aliases->next;
}
}
fprintf(source, "};\n\n");

fprintf(source, "void load_generated_sandbox(lua_State *L) {\n");
Expand All @@ -2250,7 +2320,7 @@ void emit_sandbox(void) {
fprintf(source, " lua_settable(L, -3);\n");
fprintf(source, " }\n");

// load the userdata allactors
// load the userdata allactors and globals
fprintf(source, " for (uint32_t i = 0; i < ARRAY_SIZE(new_userdata); i++) {\n");
fprintf(source, " lua_pushstring(L, new_userdata[i].name);\n");
fprintf(source, " lua_pushcfunction(L, new_userdata[i].fun);\n");
Expand Down Expand Up @@ -2468,22 +2538,25 @@ void emit_docs(struct userdata *node, int is_userdata, int emit_creation) {
// aliases
struct method_alias *alias = node->method_aliases;
while(alias) {
// find the method this is a alias of
struct method * method = node->methods;
while (method != NULL && strcmp(method->name, alias->name)) {
method = method-> next;
}
if (method == NULL) {
error(ERROR_DOCS, "Could not fine Method %s to alias to %s", alias->name, alias->alias);
}
// dont do manual bindings
if (alias->is_manual == 0) {
// find the method this is a alias of
struct method * method = node->methods;
while (method != NULL && strcmp(method->name, alias->name)) {
method = method-> next;
}
if (method == NULL) {
error(ERROR_DOCS, "Could not fine Method %s to alias to %s", alias->name, alias->alias);
}

emit_docs_method(name, alias->alias, method);
emit_docs_method(name, alias->alias, method);

alias = alias->next;
}
alias = alias->next;
}

fprintf(docs, "\n");
free(name);
fprintf(docs, "\n");
free(name);
}
node = node->next;
}
}
Expand Down Expand Up @@ -2584,6 +2657,8 @@ int main(int argc, char **argv) {
handle_singleton();
} else if (strcmp (state.token, keyword_ap_object) == 0){
handle_ap_object();
} else if (strcmp (state.token, keyword_global) == 0){
handle_global();
} else {
error(ERROR_UNKNOWN_KEYWORD, "Expected a keyword, got: %s", state.token);
}
Expand Down Expand Up @@ -2612,6 +2687,7 @@ int main(int argc, char **argv) {
fprintf(source, "#pragma GCC optimize(\"Os\")\n");
fprintf(source, "#include \"lua_generated_bindings.h\"\n");
fprintf(source, "#include <AP_Scripting/lua_boxed_numerics.h>\n");
fprintf(source, "#include <AP_Scripting/lua_bindings.h>\n");

// for set_and_print_new_error_message deprecate warning
fprintf(source, "#include <AP_Scripting/lua_scripts.h>\n");
Expand Down
55 changes: 6 additions & 49 deletions libraries/AP_Scripting/lua_bindings.cpp
@@ -1,5 +1,4 @@
#include <AP_Common/AP_Common.h>
#include <SRV_Channel/SRV_Channel.h>
#include <AP_HAL/HAL.h>
#include <AP_Logger/AP_Logger.h>

Expand Down Expand Up @@ -29,7 +28,7 @@ int check_arguments(lua_State *L, int expected_arguments, const char *fn_name) {
}

// millis
static int lua_millis(lua_State *L) {
int lua_millis(lua_State *L) {
check_arguments(L, 0, "millis");

new_uint32_t(L);
Expand All @@ -39,7 +38,7 @@ static int lua_millis(lua_State *L) {
}

// micros
static int lua_micros(lua_State *L) {
int lua_micros(lua_State *L) {
check_arguments(L, 0, "micros");

new_uint32_t(L);
Expand All @@ -48,7 +47,7 @@ static int lua_micros(lua_State *L) {
return 1;
}

static int lua_mission_receive(lua_State *L) {
int lua_mission_receive(lua_State *L) {
check_arguments(L, 0, "mission_receive");

ObjectBuffer<struct AP_Scripting::scripting_mission_cmd> *input = AP::scripting()->mission_data;
Expand Down Expand Up @@ -76,15 +75,7 @@ static int lua_mission_receive(lua_State *L) {
return 5;
}

static const luaL_Reg global_functions[] =
{
{"millis", lua_millis},
{"micros", lua_micros},
{"mission_receive", lua_mission_receive},
{NULL, NULL}
};

static int AP_Logger_Write(lua_State *L) {
int AP_Logger_Write(lua_State *L) {
AP_Logger * AP_logger = AP_Logger::get_singleton();
if (AP_logger == nullptr) {
return luaL_argerror(L, 1, "logger not supported on this firmware");
Expand Down Expand Up @@ -283,12 +274,7 @@ static int AP_Logger_Write(lua_State *L) {
return 0;
}

const luaL_Reg AP_Logger_functions[] = {
{"write", AP_Logger_Write},
{NULL, NULL}
};

static int lua_get_i2c_device(lua_State *L) {
int lua_get_i2c_device(lua_State *L) {

const int args = lua_gettop(L);
if (args < 2) {
Expand Down Expand Up @@ -342,13 +328,8 @@ static int lua_get_i2c_device(lua_State *L) {
return 1;
}

const luaL_Reg i2c_functions[] = {
{"get_device", lua_get_i2c_device},
{NULL, NULL}
};

#if HAL_MAX_CAN_PROTOCOL_DRIVERS
static int lua_get_CAN_device(lua_State *L) {
int lua_get_CAN_device(lua_State *L) {

check_arguments(L, 1, "CAN:get_device");

Expand All @@ -368,28 +349,4 @@ static int lua_get_CAN_device(lua_State *L) {

return 1;
}

const luaL_Reg CAN_functions[] = {
{"get_device", lua_get_CAN_device},
{NULL, NULL}
};
#endif // HAL_MAX_CAN_PROTOCOL_DRIVERS

void load_lua_bindings(lua_State *L) {
lua_pushstring(L, "logger");
luaL_newlib(L, AP_Logger_functions);
lua_settable(L, -3);

lua_pushstring(L, "i2c");
luaL_newlib(L, i2c_functions);
lua_settable(L, -3);

#if HAL_MAX_CAN_PROTOCOL_DRIVERS
lua_pushstring(L, "CAN");
luaL_newlib(L, CAN_functions);
lua_settable(L, -3);
#endif

luaL_setfuncs(L, global_functions, 0);
}

9 changes: 7 additions & 2 deletions libraries/AP_Scripting/lua_bindings.h
Expand Up @@ -2,5 +2,10 @@

#include "lua/src/lua.hpp"

// load all known lua bindings into the state
void load_lua_bindings(lua_State *state);
int lua_millis(lua_State *L);
int lua_micros(lua_State *L);
int lua_mission_receive(lua_State *L);
int AP_Logger_Write(lua_State *L);
int lua_get_i2c_device(lua_State *L);
int lua_get_CAN_device(lua_State *L);