mirror of https://github.com/arendst/Tasmota.git
Merge pull request #12954 from s-hadinger/berry_vararg
Berry support for vararg
This commit is contained in:
commit
bda28e9981
|
@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.
|
|||
### Added
|
||||
- Turn HTTP API (command ``SetOption128 1``) default on for backward compatibility
|
||||
- Support for IEM3155 Wattmeter (#12940)
|
||||
- Berry support for vararg
|
||||
|
||||
### Fixed
|
||||
- WDT reset on shutters with stepper motors during deceleration (#12849)
|
||||
|
|
|
@ -528,23 +528,45 @@ static void singlevar(bparser *parser, bexpdesc *var)
|
|||
}
|
||||
}
|
||||
|
||||
/* parse a vararg argument in the form `def f(a, *b) end` */
|
||||
/* Munch the '*', read the token, create variable and declare the function as vararg */
|
||||
static void func_vararg(bparser *parser) {
|
||||
bexpdesc v;
|
||||
bstring *str;
|
||||
match_token(parser, OptMul); /* skip '*' */
|
||||
str = next_token(parser).u.s;
|
||||
match_token(parser, TokenId); /* match and skip ID */
|
||||
new_var(parser, str, &v); /* new variable */
|
||||
parser->finfo->proto->varg = 1; /* set varg flag */
|
||||
}
|
||||
|
||||
/* Parse function or method definition variable list */
|
||||
/* Create an implicit local variable for each argument starting at R0 */
|
||||
/* Update function proto argc to the expected number or arguments */
|
||||
/* Raise an exception if multiple arguments have the same name */
|
||||
/* New: vararg support */
|
||||
static void func_varlist(bparser *parser)
|
||||
{
|
||||
bexpdesc v;
|
||||
bstring *str;
|
||||
/* '(' [ID {',' ID}] ')' */
|
||||
/* '(' [ ID {',' ID}] ')' or */
|
||||
/* '(' '*' ID ')' or */
|
||||
/* '(' [ ID {',' ID}] ',' '*' ID ')' */
|
||||
match_token(parser, OptLBK); /* skip '(' */
|
||||
if (match_id(parser, str) != NULL) {
|
||||
if (next_type(parser) == OptMul) {
|
||||
func_vararg(parser);
|
||||
} else if (match_id(parser, str) != NULL) {
|
||||
new_var(parser, str, &v); /* new variable */
|
||||
while (match_skip(parser, OptComma)) { /* ',' */
|
||||
str = next_token(parser).u.s;
|
||||
match_token(parser, TokenId); /* match and skip ID */
|
||||
/* new local variable */
|
||||
new_var(parser, str, &v);
|
||||
if (next_type(parser) == OptMul) {
|
||||
func_vararg(parser);
|
||||
break;
|
||||
} else {
|
||||
str = next_token(parser).u.s;
|
||||
match_token(parser, TokenId); /* match and skip ID */
|
||||
/* new local variable */
|
||||
new_var(parser, str, &v);
|
||||
}
|
||||
}
|
||||
}
|
||||
match_token(parser, OptRBK); /* skip ')' */
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "be_class.h"
|
||||
#include "be_func.h"
|
||||
#include "be_vector.h"
|
||||
#include "be_list.h"
|
||||
#include "be_map.h"
|
||||
#include "be_module.h"
|
||||
#include "be_mem.h"
|
||||
|
@ -1086,6 +1087,20 @@ newframe: /* a new call frame */
|
|||
for (; v < end; ++v) { /* set all not provided arguments to nil */
|
||||
var_setnil(v);
|
||||
}
|
||||
if (proto->varg) { /* there are vararg at the last argument, build the list */
|
||||
/* code below uses mostly low-level calls for performance */
|
||||
be_stack_require(vm, argc + 2); /* make sure we don't overflow the stack */
|
||||
bvalue *top_save = vm->top; /* save original stack, we need fresh slots to create the 'list' instance */
|
||||
vm->top = v; /* move top of stack right after last argument */
|
||||
be_newobject(vm, "list"); /* this creates 2 objects on stack: list instance, BE_LIST object */
|
||||
blist *list = var_toobj(vm->top-1); /* get low-level BE_LIST structure */
|
||||
v = reg + proto->argc - 1; /* last argument */
|
||||
for (; v < reg + argc; v++) {
|
||||
be_list_push(vm, list, v); /* push all varargs into list */
|
||||
}
|
||||
*(reg + proto->argc - 1) = *(vm->top-2); /* change the vararg argument to now contain the list instance */
|
||||
vm->top = top_save; /* restore top of stack pointer */
|
||||
}
|
||||
goto newframe; /* continue execution of the closure */
|
||||
}
|
||||
case BE_NTVCLOS: {
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
#- vararg -#
|
||||
def f(a,*b) return b end
|
||||
|
||||
assert(f() == [])
|
||||
assert(f(1) == [])
|
||||
assert(f(1,2) == [2])
|
||||
assert(f(1,2,3) == [2, 3])
|
||||
|
||||
def g(*a) return a end
|
||||
|
||||
assert(g() == [])
|
||||
assert(g("foo") == ["foo"])
|
||||
assert(g("foo", nil) == ["foo", nil])
|
||||
assert(g("foo", nil, 2) == ["foo", nil, 2])
|
|
@ -347,7 +347,7 @@ void BrLoad(const char * script_name) {
|
|||
bool loaded = be_tobool(berry.vm, -2); // did it succeed?
|
||||
be_pop(berry.vm, 2);
|
||||
if (loaded) {
|
||||
AddLog(LOG_LEVEL_INFO, D_LOG_BERRY "sucessfully loaded '%s'", script_name);
|
||||
AddLog(LOG_LEVEL_INFO, D_LOG_BERRY "successfully loaded '%s'", script_name);
|
||||
} else {
|
||||
AddLog(LOG_LEVEL_INFO, D_LOG_BERRY "no '%s'", script_name);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue