mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-24 19:26:37 +00:00
Berry extend range(lower, upper, incr)
to arbitrary increment (#19120)
This commit is contained in:
parent
af27d65a8a
commit
46e17061b2
@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
### Changed
|
### Changed
|
||||||
- ESP32 shutter driver support up to 16 shutters (#18295)
|
- ESP32 shutter driver support up to 16 shutters (#18295)
|
||||||
- Configuration backup and restore now backup and restore ``.xdrvsetXXX`` files too (#18295)
|
- Configuration backup and restore now backup and restore ``.xdrvsetXXX`` files too (#18295)
|
||||||
|
- Berry extend `range(lower, upper, incr)` to arbitrary increment
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
@ -11,31 +11,67 @@
|
|||||||
|
|
||||||
static int m_init(bvm *vm)
|
static int m_init(bvm *vm)
|
||||||
{
|
{
|
||||||
|
int argc = be_top(vm);
|
||||||
be_pushvalue(vm, 2);
|
be_pushvalue(vm, 2);
|
||||||
be_setmember(vm, 1, "__lower__");
|
be_setmember(vm, 1, "__lower__");
|
||||||
be_pop(vm, 1);
|
be_pop(vm, 1);
|
||||||
be_pushvalue(vm, 3);
|
be_pushvalue(vm, 3);
|
||||||
be_setmember(vm, 1, "__upper__");
|
be_setmember(vm, 1, "__upper__");
|
||||||
|
int incr = 1; /* default increment is '1' */
|
||||||
|
if (argc >= 4) {
|
||||||
|
incr = be_toint(vm, 4);
|
||||||
|
if (incr == 0) { be_raise(vm, "value_error", "increment cannot be zero"); }
|
||||||
|
}
|
||||||
|
be_pushint(vm, incr);
|
||||||
|
be_setmember(vm, 1, "__incr__");
|
||||||
be_return_nil(vm);
|
be_return_nil(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int m_tostring(bvm *vm)
|
static int m_tostring(bvm *vm)
|
||||||
{
|
{
|
||||||
be_pushstring(vm, "(");
|
be_getmember(vm, 1, "__incr__");
|
||||||
be_getmember(vm, 1, "__lower__");
|
int incr = be_toint(vm, -1);
|
||||||
be_tostring(vm, -1);
|
|
||||||
be_strconcat(vm, -2);
|
|
||||||
be_pop(vm, 1);
|
|
||||||
be_pushstring(vm, "..");
|
|
||||||
be_strconcat(vm, -2);
|
|
||||||
be_pop(vm, 1);
|
|
||||||
be_getmember(vm, 1, "__upper__");
|
|
||||||
be_tostring(vm, -1);
|
|
||||||
be_strconcat(vm, -2);
|
|
||||||
be_pop(vm, 1);
|
|
||||||
be_pushstring(vm, ")");
|
|
||||||
be_strconcat(vm, -2);
|
|
||||||
be_pop(vm, 1);
|
be_pop(vm, 1);
|
||||||
|
if (incr == 1) {
|
||||||
|
be_pushstring(vm, "(");
|
||||||
|
be_getmember(vm, 1, "__lower__");
|
||||||
|
be_tostring(vm, -1);
|
||||||
|
be_strconcat(vm, -2);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
be_pushstring(vm, "..");
|
||||||
|
be_strconcat(vm, -2);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
be_getmember(vm, 1, "__upper__");
|
||||||
|
be_tostring(vm, -1);
|
||||||
|
be_strconcat(vm, -2);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
be_pushstring(vm, ")");
|
||||||
|
be_strconcat(vm, -2);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
} else {
|
||||||
|
be_pushstring(vm, "range(");
|
||||||
|
be_getmember(vm, 1, "__lower__");
|
||||||
|
be_tostring(vm, -1);
|
||||||
|
be_strconcat(vm, -2);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
be_pushstring(vm, ", ");
|
||||||
|
be_strconcat(vm, -2);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
be_getmember(vm, 1, "__upper__");
|
||||||
|
be_tostring(vm, -1);
|
||||||
|
be_strconcat(vm, -2);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
be_pushstring(vm, ", ");
|
||||||
|
be_strconcat(vm, -2);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
be_getmember(vm, 1, "__incr__");
|
||||||
|
be_tostring(vm, -1);
|
||||||
|
be_strconcat(vm, -2);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
be_pushstring(vm, ")");
|
||||||
|
be_strconcat(vm, -2);
|
||||||
|
be_pop(vm, 1);
|
||||||
|
}
|
||||||
be_return(vm);
|
be_return(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,13 +87,27 @@ static int m_lower(bvm *vm)
|
|||||||
be_return(vm);
|
be_return(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int m_incr(bvm *vm)
|
||||||
|
{
|
||||||
|
be_getmember(vm, 1, "__incr__");
|
||||||
|
be_return(vm);
|
||||||
|
}
|
||||||
|
|
||||||
static int m_setrange(bvm *vm)
|
static int m_setrange(bvm *vm)
|
||||||
{
|
{
|
||||||
|
int argc = be_top(vm);
|
||||||
be_pushvalue(vm, 2);
|
be_pushvalue(vm, 2);
|
||||||
be_setmember(vm, 1, "__lower__");
|
be_setmember(vm, 1, "__lower__");
|
||||||
be_pop(vm, 1);
|
be_pop(vm, 1);
|
||||||
be_pushvalue(vm, 3);
|
be_pushvalue(vm, 3);
|
||||||
be_setmember(vm, 1, "__upper__");
|
be_setmember(vm, 1, "__upper__");
|
||||||
|
int incr = 1; /* default increment is '1' */
|
||||||
|
if (argc >= 4) {
|
||||||
|
incr = be_toint(vm, 4);
|
||||||
|
if (incr == 0) { be_raise(vm, "value_error", "increment cannot be zero"); }
|
||||||
|
}
|
||||||
|
be_pushint(vm, incr);
|
||||||
|
be_setmember(vm, 1, "__incr__");
|
||||||
be_return_nil(vm);
|
be_return_nil(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,25 +118,30 @@ static int iter_closure(bvm *vm)
|
|||||||
bntvclos *func = var_toobj(vm->cf->func);
|
bntvclos *func = var_toobj(vm->cf->func);
|
||||||
bvalue *uv0 = be_ntvclos_upval(func, 0)->value;
|
bvalue *uv0 = be_ntvclos_upval(func, 0)->value;
|
||||||
bvalue *uv1 = be_ntvclos_upval(func, 1)->value;
|
bvalue *uv1 = be_ntvclos_upval(func, 1)->value;
|
||||||
|
bvalue *uv2 = be_ntvclos_upval(func, 2)->value;
|
||||||
bint lower = var_toint(uv0); /* upvalue[0] => lower */
|
bint lower = var_toint(uv0); /* upvalue[0] => lower */
|
||||||
bint upper = var_toint(uv1); /* upvalue[1] => upper */
|
bint upper = var_toint(uv1); /* upvalue[1] => upper */
|
||||||
if (lower > upper) {
|
bint incr = var_toint(uv2); /* upvalue[2] => incr */
|
||||||
|
if ((incr > 0 && lower > upper) || (incr < 0 && lower < upper)) {
|
||||||
be_stop_iteration(vm);
|
be_stop_iteration(vm);
|
||||||
}
|
}
|
||||||
var_toint(uv0) = lower + 1; /* set upvale[0] */
|
var_toint(uv0) = lower + incr; /* set upvale[0] */
|
||||||
be_pushint(vm, lower); /* push the return value */
|
be_pushint(vm, lower); /* push the return value */
|
||||||
be_return(vm);
|
be_return(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int m_iter(bvm *vm)
|
static int m_iter(bvm *vm)
|
||||||
{
|
{
|
||||||
be_pushntvclosure(vm, iter_closure, 2);
|
be_pushntvclosure(vm, iter_closure, 3);
|
||||||
be_getmember(vm, 1, "__lower__");
|
be_getmember(vm, 1, "__lower__");
|
||||||
be_setupval(vm, -2, 0);
|
be_setupval(vm, -2, 0);
|
||||||
be_pop(vm, 1);
|
be_pop(vm, 1);
|
||||||
be_getmember(vm, 1, "__upper__");
|
be_getmember(vm, 1, "__upper__");
|
||||||
be_setupval(vm, -2, 1);
|
be_setupval(vm, -2, 1);
|
||||||
be_pop(vm, 1);
|
be_pop(vm, 1);
|
||||||
|
be_getmember(vm, 1, "__incr__");
|
||||||
|
be_setupval(vm, -2, 2);
|
||||||
|
be_pop(vm, 1);
|
||||||
be_return(vm);
|
be_return(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +151,7 @@ void be_load_rangelib(bvm *vm)
|
|||||||
static const bnfuncinfo members[] = {
|
static const bnfuncinfo members[] = {
|
||||||
{ "__lower__", NULL },
|
{ "__lower__", NULL },
|
||||||
{ "__upper__", NULL },
|
{ "__upper__", NULL },
|
||||||
|
{ "__incr__", NULL },
|
||||||
{ "init", m_init },
|
{ "init", m_init },
|
||||||
{ "tostring", m_tostring },
|
{ "tostring", m_tostring },
|
||||||
{ "lower", m_lower },
|
{ "lower", m_lower },
|
||||||
@ -111,10 +167,12 @@ void be_load_rangelib(bvm *vm)
|
|||||||
class be_class_range (scope: global, name: range) {
|
class be_class_range (scope: global, name: range) {
|
||||||
__lower__, var
|
__lower__, var
|
||||||
__upper__, var
|
__upper__, var
|
||||||
|
__incr__, var
|
||||||
init, func(m_init)
|
init, func(m_init)
|
||||||
tostring, func(m_tostring)
|
tostring, func(m_tostring)
|
||||||
lower, func(m_lower)
|
lower, func(m_lower)
|
||||||
upper, func(m_upper)
|
upper, func(m_upper)
|
||||||
|
incr, func(m_incr)
|
||||||
setrange, func(m_setrange)
|
setrange, func(m_setrange)
|
||||||
iter, func(m_iter)
|
iter, func(m_iter)
|
||||||
}
|
}
|
||||||
|
39
lib/libesp32/berry/tests/range.be
Normal file
39
lib/libesp32/berry/tests/range.be
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# test for ranges
|
||||||
|
|
||||||
|
# expand a range object as list
|
||||||
|
def expand(iter)
|
||||||
|
var ret = []
|
||||||
|
for i: iter
|
||||||
|
ret.push(i)
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(expand(0..5) == [0, 1, 2, 3, 4, 5])
|
||||||
|
assert(expand(0..0) == [0])
|
||||||
|
assert(expand(5..0) == [])
|
||||||
|
var r = 1..5
|
||||||
|
assert(r.lower() == 1)
|
||||||
|
assert(r.upper() == 5)
|
||||||
|
assert(r.incr() == 1)
|
||||||
|
|
||||||
|
assert(expand(range(0,5)) == [0, 1, 2, 3, 4, 5])
|
||||||
|
assert(expand(range(0,5,2)) == [0, 2, 4])
|
||||||
|
assert(expand(range(0,5,12)) == [0])
|
||||||
|
assert(expand(range(0,5,-1)) == [])
|
||||||
|
|
||||||
|
assert(expand(range(5,0,-1)) == [5, 4, 3, 2, 1, 0])
|
||||||
|
assert(expand(range(5,0,-2)) == [5, 3, 1])
|
||||||
|
assert(expand(range(5,5,-2)) == [5])
|
||||||
|
assert(expand(range(0,5,-2)) == [])
|
||||||
|
|
||||||
|
def assert_value_error(c)
|
||||||
|
try
|
||||||
|
compile(c)()
|
||||||
|
assert(false, 'unexpected execution flow')
|
||||||
|
except 'value_error' as e, m
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# range with increment zero shoud raise an error
|
||||||
|
assert_value_error("range(1,2,0)")
|
Loading…
x
Reference in New Issue
Block a user