AP_Scripting: Add alias suppport to the scripting generator

This commit is contained in:
Michael du Breuil 2019-04-15 15:11:26 -07:00 committed by Andrew Tridgell
parent 746240ebe3
commit e4035bd7e8
4 changed files with 60 additions and 27 deletions

View File

@ -29,8 +29,8 @@ An example script is given below:
```lua
function update () -- periodic function that will be called
current_pos = Location()
AP_AHRS:get_position(current_pos)
distance = current_pos:get_distance(AP_AHRS:get_home()) -- calculate the distance from home
ahrs:get_position(current_pos)
distance = current_pos:get_distance(ahrs:get_home()) -- calculate the distance from home
if distance > 1000 then -- if more then 1000 meters away
distance = 1000; -- clamp the distance to 1000 meters
end

View File

@ -15,6 +15,7 @@ userdata Location method get_vector_from_origin_NEU boolean Vector3f
include AP_AHRS/AP_AHRS.h
singleton AP_AHRS alias ahrs
singleton AP_AHRS method get_position boolean Location
singleton AP_AHRS method get_home Location
@ -25,7 +26,9 @@ userdata Vector3f field y float read write -FLT_MAX FLT_MAX
userdata Vector3f field z float read write -FLT_MAX FLT_MAX
include AP_Notify/AP_Notify.h
singleton notify alias notify
singleton AP_Notify method play_tune void string
include AP_RangeFinder/AP_RangeFinder.h
singleton RangeFinder alias rangefinder
singleton RangeFinder method num_sensors uint8_t

View File

@ -6,6 +6,7 @@
#include <string.h>
#include <unistd.h>
char keyword_alias[] = "alias";
char keyword_comment[] = "--";
char keyword_field[] = "field";
char keyword_include[] = "include";
@ -505,7 +506,8 @@ void handle_userdata(void) {
struct singleton {
struct singleton *next;
char *name;
char *name; // name of the C++ singleton
char *alias; // (optional) used for scripting access
struct method * methods;
};
@ -538,12 +540,28 @@ void handle_singleton(void) {
if (type == NULL) {
error(ERROR_SINGLETON, "Expected an access type for userdata %s", name);
}
if (strcmp(type, keyword_method) != 0) {
error(ERROR_SINGLETON, "Singletons only support method access types (got %s)", type);
}
// method name
handle_method(TRACE_USERDATA, node->name, &(node->methods));
if (strcmp(type, keyword_alias) == 0) {
if (node->alias != NULL) {
error(ERROR_SINGLETON, "Alias of %s was already declared for %s", node->alias, node->name);
}
const char *alias = next_token();
if (alias == NULL) {
error(ERROR_SINGLETON, "Missing the name of the alias for %s", node->name);
}
node->alias = (char *)allocate(strlen(alias) + 1);
strcpy(node->alias, alias);
// ensure no more tokens on the line
if (next_token()) {
error(ERROR_HEADER, "Singleton contained an unexpected extra token: %s", state.token);
}
return;
} else if (strcmp(type, keyword_method) == 0) {
handle_method(TRACE_USERDATA, node->name, &(node->methods));
} else {
error(ERROR_SINGLETON, "Singletons only support methods or aliases (got %s)", type);
}
}
@ -841,6 +859,8 @@ void emit_singleton_method(const struct singleton *data, const struct method *me
arg = arg->next;
}
const char *access_name = data->alias ? data->alias : data->name;
fprintf(source, "int %s_%s(lua_State *L) {\n", data->name, method->name);
fprintf(source, " const int args = lua_gettop(L);\n");
fprintf(source, " if (args > %d) {\n", arg_count);
@ -848,12 +868,12 @@ void emit_singleton_method(const struct singleton *data, const struct method *me
fprintf(source, " } else if (args < %d) {\n", arg_count);
fprintf(source, " return luaL_argerror(L, args, \"too few arguments\");\n");
fprintf(source, " }\n\n");
fprintf(source, " luaL_checkudata(L, 1, \"%s\");\n\n", data->name);
fprintf(source, " luaL_checkudata(L, 1, \"%s\");\n\n", access_name);
// fetch and check the singleton pointer
fprintf(source, " %s *singleton = %s::get_singleton();", data->name, data->name);
fprintf(source, " %s *singleton = %s::get_singleton();\n", data->name, data->name);
fprintf(source, " if (singleton == nullptr) {\n");
fprintf(source, " return luaL_argerror(L, args, \"%s not supported on this firmware\");\n", data->name);
fprintf(source, " return luaL_argerror(L, args, \"%s not supported on this firmware\");\n", access_name);
fprintf(source, " }\n\n");
// extract the arguments
@ -1016,7 +1036,7 @@ void emit_loaders(void) {
fprintf(source, "} singleton_fun[] = {\n");
struct singleton * single = parsed_singletons;
while (single) {
fprintf(source, " {\"%s\", %s_meta},\n", single->name, single->name);
fprintf(source, " {\"%s\", %s_meta},\n", single->alias ? single->alias : single->name, single->name);
single = single->next;
}
fprintf(source, "};\n\n");
@ -1054,7 +1074,7 @@ void emit_sandbox(void) {
struct singleton *single = parsed_singletons;
fprintf(source, "const char *singletons[] = {\n");
while (single) {
fprintf(source, " \"%s\",\n", single->name);
fprintf(source, " \"%s\",\n", single->alias ? single->alias : single->name);
single = single->next;
}
fprintf(source, "};\n\n");

View File

@ -264,10 +264,11 @@ int RangeFinder_num_sensors(lua_State *L) {
return luaL_argerror(L, args, "too few arguments");
}
luaL_checkudata(L, 1, "RangeFinder");
luaL_checkudata(L, 1, "rangefinder");
RangeFinder *singleton = RangeFinder::get_singleton(); if (singleton == nullptr) {
return luaL_argerror(L, args, "RangeFinder not supported on this firmware");
RangeFinder *singleton = RangeFinder::get_singleton();
if (singleton == nullptr) {
return luaL_argerror(L, args, "rangefinder not supported on this firmware");
}
const uint8_t data = singleton->num_sensors(
@ -287,7 +288,8 @@ int AP_Notify_play_tune(lua_State *L) {
luaL_checkudata(L, 1, "AP_Notify");
AP_Notify *singleton = AP_Notify::get_singleton(); if (singleton == nullptr) {
AP_Notify *singleton = AP_Notify::get_singleton();
if (singleton == nullptr) {
return luaL_argerror(L, args, "AP_Notify not supported on this firmware");
}
@ -306,10 +308,11 @@ int AP_AHRS_get_home(lua_State *L) {
return luaL_argerror(L, args, "too few arguments");
}
luaL_checkudata(L, 1, "AP_AHRS");
luaL_checkudata(L, 1, "ahrs");
AP_AHRS *singleton = AP_AHRS::get_singleton(); if (singleton == nullptr) {
return luaL_argerror(L, args, "AP_AHRS not supported on this firmware");
AP_AHRS *singleton = AP_AHRS::get_singleton();
if (singleton == nullptr) {
return luaL_argerror(L, args, "ahrs not supported on this firmware");
}
const Location &data = singleton->get_home(
@ -328,10 +331,11 @@ int AP_AHRS_get_position(lua_State *L) {
return luaL_argerror(L, args, "too few arguments");
}
luaL_checkudata(L, 1, "AP_AHRS");
luaL_checkudata(L, 1, "ahrs");
AP_AHRS *singleton = AP_AHRS::get_singleton(); if (singleton == nullptr) {
return luaL_argerror(L, args, "AP_AHRS not supported on this firmware");
AP_AHRS *singleton = AP_AHRS::get_singleton();
if (singleton == nullptr) {
return luaL_argerror(L, args, "ahrs not supported on this firmware");
}
Location & data_2 = *check_Location(L, 2);
@ -352,6 +356,10 @@ const luaL_Reg AP_Notify_meta[] = {
{NULL, NULL}
};
const luaL_Reg notify_meta[] = {
{NULL, NULL}
};
const luaL_Reg AP_AHRS_meta[] = {
{"get_home", AP_AHRS_get_home},
{"get_position", AP_AHRS_get_position},
@ -370,9 +378,10 @@ const struct singleton_fun {
const char *name;
const luaL_Reg *reg;
} singleton_fun[] = {
{"RangeFinder", RangeFinder_meta},
{"rangefinder", RangeFinder_meta},
{"AP_Notify", AP_Notify_meta},
{"AP_AHRS", AP_AHRS_meta},
{"notify", notify_meta},
{"ahrs", AP_AHRS_meta},
};
void load_generated_bindings(lua_State *L) {
@ -402,9 +411,10 @@ void load_generated_bindings(lua_State *L) {
}
const char *singletons[] = {
"RangeFinder",
"rangefinder",
"AP_Notify",
"AP_AHRS",
"notify",
"ahrs",
};
const struct userdata {