Skip to content

Commit

Permalink
Berry extend range(lower, upper, incr) to arbitrary increment (#19120)
Browse files Browse the repository at this point in the history
  • Loading branch information
s-hadinger committed Jul 15, 2023
1 parent af27d65 commit 46e1706
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file.
### Changed
- ESP32 shutter driver support up to 16 shutters (#18295)
- Configuration backup and restore now backup and restore ``.xdrvsetXXX`` files too (#18295)
- Berry extend `range(lower, upper, incr)` to arbitrary increment

### Fixed

Expand Down
92 changes: 75 additions & 17 deletions lib/libesp32/berry/src/be_rangelib.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,67 @@

static int m_init(bvm *vm)
{
int argc = be_top(vm);
be_pushvalue(vm, 2);
be_setmember(vm, 1, "__lower__");
be_pop(vm, 1);
be_pushvalue(vm, 3);
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);
}

static int m_tostring(bvm *vm)
{
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_getmember(vm, 1, "__incr__");
int incr = be_toint(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);
}

Expand All @@ -51,13 +87,27 @@ static int m_lower(bvm *vm)
be_return(vm);
}

static int m_incr(bvm *vm)
{
be_getmember(vm, 1, "__incr__");
be_return(vm);
}

static int m_setrange(bvm *vm)
{
int argc = be_top(vm);
be_pushvalue(vm, 2);
be_setmember(vm, 1, "__lower__");
be_pop(vm, 1);
be_pushvalue(vm, 3);
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);
}

Expand All @@ -68,25 +118,30 @@ static int iter_closure(bvm *vm)
bntvclos *func = var_toobj(vm->cf->func);
bvalue *uv0 = be_ntvclos_upval(func, 0)->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 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);
}
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_return(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_setupval(vm, -2, 0);
be_pop(vm, 1);
be_getmember(vm, 1, "__upper__");
be_setupval(vm, -2, 1);
be_pop(vm, 1);
be_getmember(vm, 1, "__incr__");
be_setupval(vm, -2, 2);
be_pop(vm, 1);
be_return(vm);
}

Expand All @@ -96,6 +151,7 @@ void be_load_rangelib(bvm *vm)
static const bnfuncinfo members[] = {
{ "__lower__", NULL },
{ "__upper__", NULL },
{ "__incr__", NULL },
{ "init", m_init },
{ "tostring", m_tostring },
{ "lower", m_lower },
Expand All @@ -111,10 +167,12 @@ void be_load_rangelib(bvm *vm)
class be_class_range (scope: global, name: range) {
__lower__, var
__upper__, var
__incr__, var
init, func(m_init)
tostring, func(m_tostring)
lower, func(m_lower)
upper, func(m_upper)
incr, func(m_incr)
setrange, func(m_setrange)
iter, func(m_iter)
}
Expand Down
39 changes: 39 additions & 0 deletions lib/libesp32/berry/tests/range.be
Original file line number Diff line number Diff line change
@@ -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)")

0 comments on commit 46e1706

Please sign in to comment.