mirror of https://github.com/arendst/Tasmota.git
Merge pull request #13107 from arendst/revert-13101-berry_call
Revert "Berry move introspect.vcall to call"
This commit is contained in:
commit
f598f5f79f
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -2,13 +2,14 @@
|
|||
|
||||
static be_define_const_map_slots(m_libintrospect_map) {
|
||||
{ be_const_key(members, -1), be_const_func(m_attrlist) },
|
||||
{ be_const_key(set, -1), be_const_func(m_setmember) },
|
||||
{ be_const_key(vcall, -1), be_const_func(m_vcall) },
|
||||
{ be_const_key(get, -1), be_const_func(m_findmember) },
|
||||
{ be_const_key(set, 2), be_const_func(m_setmember) },
|
||||
};
|
||||
|
||||
static be_define_const_map(
|
||||
m_libintrospect_map,
|
||||
3
|
||||
4
|
||||
);
|
||||
|
||||
static be_define_const_module(
|
||||
|
|
|
@ -1,41 +1,39 @@
|
|||
#include "be_constobj.h"
|
||||
|
||||
static be_define_const_map_slots(m_builtin_map) {
|
||||
{ be_const_key(number, 16), be_const_int(14) },
|
||||
{ be_const_key(map, -1), be_const_int(12) },
|
||||
{ be_const_key(classname, 22), be_const_int(4) },
|
||||
{ be_const_key(bytes, 2), be_const_int(2) },
|
||||
{ be_const_key(int, 12), be_const_int(8) },
|
||||
{ be_const_key(module, -1), be_const_int(13) },
|
||||
{ be_const_key(print, 20), be_const_int(16) },
|
||||
{ be_const_key(issubclass, -1), be_const_int(10) },
|
||||
{ be_const_key(assert, -1), be_const_int(1) },
|
||||
{ be_const_key(list, -1), be_const_int(11) },
|
||||
{ be_const_key(print, 19), be_const_int(15) },
|
||||
{ be_const_key(isinstance, -1), be_const_int(8) },
|
||||
{ be_const_key(classname, -1), be_const_int(3) },
|
||||
{ be_const_key(module, -1), be_const_int(12) },
|
||||
{ be_const_key(size, -1), be_const_int(18) },
|
||||
{ be_const_key(type, 9), be_const_int(21) },
|
||||
{ be_const_key(compile, -1), be_const_int(5) },
|
||||
{ be_const_key(open, -1), be_const_int(14) },
|
||||
{ be_const_key(real, -1), be_const_int(17) },
|
||||
{ be_const_key(__iterator__, -1), be_const_int(0) },
|
||||
{ be_const_key(real, -1), be_const_int(18) },
|
||||
{ be_const_key(super, 21), be_const_int(21) },
|
||||
{ be_const_key(isinstance, 8), be_const_int(9) },
|
||||
{ be_const_key(classof, 4), be_const_int(5) },
|
||||
{ be_const_key(input, -1), be_const_int(7) },
|
||||
{ be_const_key(call, 19), be_const_int(3) },
|
||||
{ be_const_key(compile, -1), be_const_int(6) },
|
||||
{ be_const_key(open, -1), be_const_int(15) },
|
||||
{ be_const_key(size, -1), be_const_int(19) },
|
||||
{ be_const_key(range, -1), be_const_int(17) },
|
||||
{ be_const_key(str, -1), be_const_int(20) },
|
||||
{ be_const_key(type, -1), be_const_int(22) },
|
||||
{ be_const_key(super, -1), be_const_int(20) },
|
||||
{ be_const_key(issubclass, -1), be_const_int(9) },
|
||||
{ be_const_key(classof, -1), be_const_int(4) },
|
||||
{ be_const_key(map, 8), be_const_int(11) },
|
||||
{ be_const_key(int, 2), be_const_int(7) },
|
||||
{ be_const_key(input, 3), be_const_int(6) },
|
||||
{ be_const_key(number, -1), be_const_int(13) },
|
||||
{ be_const_key(list, 7), be_const_int(10) },
|
||||
{ be_const_key(str, 1), be_const_int(19) },
|
||||
{ be_const_key(range, -1), be_const_int(16) },
|
||||
{ be_const_key(bytes, -1), be_const_int(2) },
|
||||
{ be_const_key(assert, -1), be_const_int(1) },
|
||||
};
|
||||
|
||||
static be_define_const_map(
|
||||
m_builtin_map,
|
||||
23
|
||||
22
|
||||
);
|
||||
|
||||
static const bvalue __vlist_array[] = {
|
||||
be_const_func(l_iterator),
|
||||
be_const_func(l_assert),
|
||||
be_const_class(be_class_bytes),
|
||||
be_const_func(l_call),
|
||||
be_const_func(l_classname),
|
||||
be_const_func(l_classof),
|
||||
be_const_func(l_compile),
|
||||
|
@ -60,5 +58,5 @@ static const bvalue __vlist_array[] = {
|
|||
static be_define_const_vector(
|
||||
m_builtin_vector,
|
||||
__vlist_array,
|
||||
23
|
||||
22
|
||||
);
|
||||
|
|
|
@ -277,55 +277,6 @@ static int l_iterator(bvm *vm)
|
|||
be_return_nil(vm);
|
||||
}
|
||||
|
||||
/* call a function with variable number of arguments */
|
||||
/* first argument is a callable object (function, closure, native function, native closure) */
|
||||
/* then all subsequent arguments are pushed except the last one */
|
||||
/* If the last argument is a 'list', then all elements are pushed as arguments */
|
||||
/* otherwise the last argument is pushed as well */
|
||||
static int l_call(bvm *vm)
|
||||
{
|
||||
int top = be_top(vm);
|
||||
if (top >= 1 && be_isfunction(vm, 1)) {
|
||||
size_t arg_count = top - 1; /* we have at least 'top - 1' arguments */
|
||||
/* test if last argument is a list */
|
||||
|
||||
if (top > 1 && be_isinstance(vm, top) && be_getmember(vm, top, ".p") && be_islist(vm, top + 1)) {
|
||||
int32_t list_size = be_data_size(vm, top + 1);
|
||||
|
||||
if (list_size > 0) {
|
||||
be_stack_require(vm, list_size + 3); /* make sure we don't overflow the stack */
|
||||
for (int i = 0; i < list_size; i++) {
|
||||
be_pushnil(vm);
|
||||
}
|
||||
be_moveto(vm, top + 1, top + 1 + list_size);
|
||||
be_moveto(vm, top, top + list_size);
|
||||
|
||||
be_refpush(vm, -2);
|
||||
be_pushiter(vm, -1);
|
||||
while (be_iter_hasnext(vm, -2)) {
|
||||
be_iter_next(vm, -2);
|
||||
be_moveto(vm, -1, top);
|
||||
top++;
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
be_pop(vm, 1); /* remove iterator */
|
||||
be_refpop(vm);
|
||||
}
|
||||
be_pop(vm, 2);
|
||||
arg_count = arg_count - 1 + list_size;
|
||||
}
|
||||
/* actual call */
|
||||
be_call(vm, arg_count);
|
||||
/* remove args */
|
||||
be_pop(vm, arg_count);
|
||||
/* return value */
|
||||
|
||||
be_return(vm);
|
||||
}
|
||||
be_raise(vm, "value_error", "first argument must be a function");
|
||||
be_return_nil(vm);
|
||||
}
|
||||
|
||||
static int l_str(bvm *vm)
|
||||
{
|
||||
if (be_top(vm)) {
|
||||
|
@ -455,7 +406,6 @@ void be_load_baselib(bvm *vm)
|
|||
be_regfunc(vm, "issubclass", l_issubclass);
|
||||
be_regfunc(vm, "isinstance", l_isinstance);
|
||||
be_regfunc(vm, "__iterator__", l_iterator);
|
||||
be_regfunc(vm, "call", l_call);
|
||||
}
|
||||
#else
|
||||
extern const bclass be_class_list;
|
||||
|
@ -482,7 +432,6 @@ vartab m_builtin (scope: local) {
|
|||
issubclass, func(l_issubclass)
|
||||
isinstance, func(l_isinstance)
|
||||
__iterator__, func(l_iterator)
|
||||
call, func(l_call)
|
||||
open, func(be_nfunc_open)
|
||||
list, class(be_class_list)
|
||||
map, class(be_class_map)
|
||||
|
|
|
@ -76,12 +76,62 @@ static int m_setmember(bvm *vm)
|
|||
be_return_nil(vm);
|
||||
}
|
||||
|
||||
/* call a function with variable number of arguments */
|
||||
/* first argument is a callable object (function, closure, native function, native closure) */
|
||||
/* then all subsequent arguments are pushed except the last one */
|
||||
/* If the last argument is a 'list', then all elements are pushed as arguments */
|
||||
/* otherwise the last argument is pushed as well */
|
||||
static int m_vcall(bvm *vm)
|
||||
{
|
||||
int top = be_top(vm);
|
||||
if (top >= 1 && be_isfunction(vm, 1)) {
|
||||
size_t arg_count = top - 1; /* we have at least 'top - 1' arguments */
|
||||
/* test if last argument is a list */
|
||||
|
||||
if (top > 1 && be_isinstance(vm, top) && be_getmember(vm, top, ".p") && be_islist(vm, top + 1)) {
|
||||
int32_t list_size = be_data_size(vm, top + 1);
|
||||
|
||||
if (list_size > 0) {
|
||||
be_stack_require(vm, list_size + 3); /* make sure we don't overflow the stack */
|
||||
for (int i = 0; i < list_size; i++) {
|
||||
be_pushnil(vm);
|
||||
}
|
||||
be_moveto(vm, top + 1, top + 1 + list_size);
|
||||
be_moveto(vm, top, top + list_size);
|
||||
|
||||
be_refpush(vm, -2);
|
||||
be_pushiter(vm, -1);
|
||||
while (be_iter_hasnext(vm, -2)) {
|
||||
be_iter_next(vm, -2);
|
||||
be_moveto(vm, -1, top);
|
||||
top++;
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
be_pop(vm, 1); /* remove iterator */
|
||||
be_refpop(vm);
|
||||
}
|
||||
be_pop(vm, 2);
|
||||
arg_count = arg_count - 1 + list_size;
|
||||
}
|
||||
/* actual call */
|
||||
be_call(vm, arg_count);
|
||||
/* remove args */
|
||||
be_pop(vm, arg_count);
|
||||
/* return value */
|
||||
|
||||
be_return(vm);
|
||||
}
|
||||
be_raise(vm, "value_error", "first argument must be a function");
|
||||
be_return_nil(vm);
|
||||
}
|
||||
|
||||
#if !BE_USE_PRECOMPILED_OBJECT
|
||||
be_native_module_attr_table(introspect) {
|
||||
be_native_module_function("members", m_attrlist),
|
||||
|
||||
be_native_module_function("get", m_findmember),
|
||||
be_native_module_function("set", m_setmember),
|
||||
be_native_module_function("vcall", m_vcall),
|
||||
};
|
||||
|
||||
be_define_native_module(introspect, NULL);
|
||||
|
@ -92,6 +142,7 @@ module introspect (scope: global, depend: BE_USE_INTROSPECT_MODULE) {
|
|||
|
||||
get, func(m_findmember)
|
||||
set, func(m_setmember)
|
||||
vcall, func(m_vcall)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "../generate/be_fixed_introspect.h"
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
#- -#
|
||||
#- witness function dumping first 3 args -#
|
||||
#- -#
|
||||
def f(a,b,c) return [a,b,c] end
|
||||
|
||||
#- simple calls with fixed args -#
|
||||
assert(call(f) == [nil, nil, nil])
|
||||
assert(call(f, 1) == [1, nil, nil])
|
||||
assert(call(f, 1, 2) == [1, 2, nil])
|
||||
assert(call(f, 1, 2, 3, 4) == [1, 2, 3])
|
||||
|
||||
#- call with var args -#
|
||||
assert(call(f, []) == [nil, nil, nil])
|
||||
assert(call(f, [1]) == [1, nil, nil])
|
||||
assert(call(f, [1, 2]) == [1, 2, nil])
|
||||
assert(call(f, [1, 2, 3, 4]) == [1, 2, 3])
|
||||
|
||||
#- mixed args -#
|
||||
assert(call(f, 1, []) == [1, nil, nil])
|
||||
assert(call(f, 1, [2]) == [1, 2, nil])
|
||||
assert(call(f, 1, [2, "foo", 4]) == [1, 2, "foo"])
|
||||
|
||||
#- non terminal list -#
|
||||
assert(call(f, 1, [2, 3, 4], "foo") == [1, [2, 3, 4], "foo"])
|
||||
|
||||
#- -#
|
||||
#- same tests with vararg function -#
|
||||
#- -#
|
||||
def g(a, *b)
|
||||
if size(b) == 0 return [a, nil, nil]
|
||||
elif size(b) == 1 return [a, b[0], nil]
|
||||
elif size(b) > 1 return [a, b[0], b[1]]
|
||||
end
|
||||
end
|
||||
|
||||
#- simple calls with fixed args -#
|
||||
assert(call(g) == [nil, nil, nil])
|
||||
assert(call(g, 1) == [1, nil, nil])
|
||||
assert(call(g, 1, 2) == [1, 2, nil])
|
||||
assert(call(g, 1, 2, 3, 4) == [1, 2, 3])
|
||||
|
||||
#- call with var args -#
|
||||
assert(call(g, []) == [nil, nil, nil])
|
||||
assert(call(g, [1]) == [1, nil, nil])
|
||||
assert(call(g, [1, 2]) == [1, 2, nil])
|
||||
assert(call(g, [1, 2, 3, 4]) == [1, 2, 3])
|
||||
|
||||
#- mixed args -#
|
||||
assert(call(g, 1, []) == [1, nil, nil])
|
||||
assert(call(g, 1, [2]) == [1, 2, nil])
|
||||
assert(call(g, 1, [2, "foo", 4]) == [1, 2, "foo"])
|
||||
|
||||
#- non terminal list -#
|
||||
assert(call(g, 1, [2, 3, 4], "foo") == [1, [2, 3, 4], "foo"])
|
||||
|
||||
#- -#
|
||||
#- test with vararg only -#
|
||||
#- -#
|
||||
def c(*a) return size(a) end
|
||||
|
||||
#- simple calls with fixed args -#
|
||||
assert(call(c) == 0)
|
||||
assert(call(c, 1) == 1)
|
||||
assert(call(c, 1, 2) == 2)
|
||||
assert(call(c, 1, 2, 3, 4) == 4)
|
||||
|
||||
#- call with var args -#
|
||||
assert(call(c, []) == 0)
|
||||
assert(call(c, [1]) == 1)
|
||||
assert(call(c, [1, 2]) == 2)
|
||||
assert(call(c, [1, 2, 3, 4]) == 4)
|
||||
|
||||
#- mixed args -#
|
||||
assert(call(c, 1, []) == 1)
|
||||
assert(call(c, 1, [2]) == 2)
|
||||
assert(call(c, 1, [2, "foo", 4]) == 4)
|
||||
|
||||
#- non terminal list -#
|
||||
assert(call(c, 1, [2, 3, 4], "foo") == 3)
|
||||
|
||||
#- -#
|
||||
#- test with native function -#
|
||||
#- -#
|
||||
import string
|
||||
|
||||
assert(call(string.format, "a") == "a")
|
||||
assert(call(string.format, "%i", 1) == "1")
|
||||
assert(call(string.format, "%i - %i", 1, 2) == "1 - 2")
|
||||
|
||||
assert(call(string.format, "%i - %i", [1, 2]) == "1 - 2")
|
||||
assert(call(string.format, "%i - %i", [1, 2, 3]) == "1 - 2")
|
||||
|
||||
assert(call(string.format, "%i - %i", 1, [1, 2, 3]) == "1 - 1")
|
||||
|
||||
#- -#
|
||||
#- try with an insanely high number of arguments to check that we don't blow up the stack -#
|
||||
#- -#
|
||||
l50 = []
|
||||
for i:1..50 l50.push(i) end
|
||||
|
||||
assert(call(g, l50) == [1, 2, 3])
|
||||
assert(call(c, l50) == 50)
|
|
@ -0,0 +1,96 @@
|
|||
#- introspect vcall -#
|
||||
import introspect
|
||||
|
||||
#- -#
|
||||
#- witness function dumping first 3 args -#
|
||||
#- -#
|
||||
def f(a,b,c) return [a,b,c] end
|
||||
|
||||
#- simple calls with fixed args -#
|
||||
assert(introspect.vcall(f) == [nil, nil, nil])
|
||||
assert(introspect.vcall(f, 1) == [1, nil, nil])
|
||||
assert(introspect.vcall(f, 1, 2) == [1, 2, nil])
|
||||
assert(introspect.vcall(f, 1, 2, 3, 4) == [1, 2, 3])
|
||||
|
||||
#- call with var args -#
|
||||
assert(introspect.vcall(f, []) == [nil, nil, nil])
|
||||
assert(introspect.vcall(f, [1]) == [1, nil, nil])
|
||||
assert(introspect.vcall(f, [1, 2]) == [1, 2, nil])
|
||||
assert(introspect.vcall(f, [1, 2, 3, 4]) == [1, 2, 3])
|
||||
|
||||
#- mixed args -#
|
||||
assert(introspect.vcall(f, 1, []) == [1, nil, nil])
|
||||
assert(introspect.vcall(f, 1, [2]) == [1, 2, nil])
|
||||
assert(introspect.vcall(f, 1, [2, "foo", 4]) == [1, 2, "foo"])
|
||||
|
||||
#- non terminal list -#
|
||||
assert(introspect.vcall(f, 1, [2, 3, 4], "foo") == [1, [2, 3, 4], "foo"])
|
||||
|
||||
#- -#
|
||||
#- same tests with vararg function -#
|
||||
#- -#
|
||||
def g(a, *b)
|
||||
if size(b) == 0 return [a, nil, nil]
|
||||
elif size(b) == 1 return [a, b[0], nil]
|
||||
elif size(b) > 1 return [a, b[0], b[1]]
|
||||
end
|
||||
end
|
||||
|
||||
#- simple calls with fixed args -#
|
||||
assert(introspect.vcall(g) == [nil, nil, nil])
|
||||
assert(introspect.vcall(g, 1) == [1, nil, nil])
|
||||
assert(introspect.vcall(g, 1, 2) == [1, 2, nil])
|
||||
assert(introspect.vcall(g, 1, 2, 3, 4) == [1, 2, 3])
|
||||
|
||||
#- call with var args -#
|
||||
assert(introspect.vcall(g, []) == [nil, nil, nil])
|
||||
assert(introspect.vcall(g, [1]) == [1, nil, nil])
|
||||
assert(introspect.vcall(g, [1, 2]) == [1, 2, nil])
|
||||
assert(introspect.vcall(g, [1, 2, 3, 4]) == [1, 2, 3])
|
||||
|
||||
#- mixed args -#
|
||||
assert(introspect.vcall(g, 1, []) == [1, nil, nil])
|
||||
assert(introspect.vcall(g, 1, [2]) == [1, 2, nil])
|
||||
assert(introspect.vcall(g, 1, [2, "foo", 4]) == [1, 2, "foo"])
|
||||
|
||||
#- non terminal list -#
|
||||
assert(introspect.vcall(g, 1, [2, 3, 4], "foo") == [1, [2, 3, 4], "foo"])
|
||||
|
||||
#- -#
|
||||
#- test with vararg only -#
|
||||
#- -#
|
||||
def c(*a) return size(a) end
|
||||
|
||||
#- simple calls with fixed args -#
|
||||
assert(introspect.vcall(c) == 0)
|
||||
assert(introspect.vcall(c, 1) == 1)
|
||||
assert(introspect.vcall(c, 1, 2) == 2)
|
||||
assert(introspect.vcall(c, 1, 2, 3, 4) == 4)
|
||||
|
||||
#- call with var args -#
|
||||
assert(introspect.vcall(c, []) == 0)
|
||||
assert(introspect.vcall(c, [1]) == 1)
|
||||
assert(introspect.vcall(c, [1, 2]) == 2)
|
||||
assert(introspect.vcall(c, [1, 2, 3, 4]) == 4)
|
||||
|
||||
#- mixed args -#
|
||||
assert(introspect.vcall(c, 1, []) == 1)
|
||||
assert(introspect.vcall(c, 1, [2]) == 2)
|
||||
assert(introspect.vcall(c, 1, [2, "foo", 4]) == 4)
|
||||
|
||||
#- non terminal list -#
|
||||
assert(introspect.vcall(c, 1, [2, 3, 4], "foo") == 3)
|
||||
|
||||
#- -#
|
||||
#- test with native function -#
|
||||
#- -#
|
||||
import string
|
||||
|
||||
assert(introspect.vcall(string.format, "a") == "a")
|
||||
assert(introspect.vcall(string.format, "%i", 1) == "1")
|
||||
assert(introspect.vcall(string.format, "%i - %i", 1, 2) == "1 - 2")
|
||||
|
||||
assert(introspect.vcall(string.format, "%i - %i", [1, 2]) == "1 - 2")
|
||||
assert(introspect.vcall(string.format, "%i - %i", [1, 2, 3]) == "1 - 2")
|
||||
|
||||
assert(introspect.vcall(string.format, "%i - %i", 1, [1, 2, 3]) == "1 - 1")
|
Loading…
Reference in New Issue