mirror of https://github.com/arendst/Tasmota.git
Berry add module `global`
This commit is contained in:
parent
f49adad496
commit
a6591ab6dd
|
@ -100,7 +100,7 @@ void be_load_driver_i2c_lib(bvm *vm) {
|
|||
}
|
||||
/* @const_object_info_begin
|
||||
|
||||
class be_class_tasmota_i2c_driver (scope: global, name: I2C_Driver, super: be_class_Driver) {
|
||||
class be_class_tasmota_i2c_driver (scope: global, name: I2C_Driver, super: be_class_tasmota_driver) {
|
||||
wire, var
|
||||
addr, var
|
||||
name, var
|
||||
|
|
|
@ -15,6 +15,7 @@ be_extern_native_module(json);
|
|||
be_extern_native_module(math);
|
||||
be_extern_native_module(time);
|
||||
be_extern_native_module(os);
|
||||
be_extern_native_module(global);
|
||||
be_extern_native_module(sys);
|
||||
be_extern_native_module(debug);
|
||||
be_extern_native_module(gc);
|
||||
|
@ -50,6 +51,9 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = {
|
|||
#if BE_USE_OS_MODULE
|
||||
&be_native_module(os),
|
||||
#endif
|
||||
#if BE_USE_GLOBAL_MODULE
|
||||
&be_native_module(global),
|
||||
#endif
|
||||
#if BE_USE_SYS_MODULE
|
||||
&be_native_module(sys),
|
||||
#endif
|
||||
|
|
|
@ -153,6 +153,7 @@
|
|||
#define BE_USE_MATH_MODULE 1
|
||||
#define BE_USE_TIME_MODULE 0
|
||||
#define BE_USE_OS_MODULE 0
|
||||
#define BE_USE_GLOBAL_MODULE 1
|
||||
#define BE_USE_SYS_MODULE 0
|
||||
#define BE_USE_DEBUG_MODULE 1
|
||||
#define BE_USE_GC_MODULE 1
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,19 @@
|
|||
#include "be_constobj.h"
|
||||
|
||||
static be_define_const_map_slots(m_libglobal_map) {
|
||||
{ be_const_key(member, -1), be_const_func(m_findglobal) },
|
||||
{ be_const_key(setmember, 0), be_const_func(m_setglobal) },
|
||||
{ be_const_key(opt_call, -1), be_const_func(m_globals) },
|
||||
};
|
||||
|
||||
static be_define_const_map(
|
||||
m_libglobal_map,
|
||||
3
|
||||
);
|
||||
|
||||
static be_define_const_module(
|
||||
m_libglobal,
|
||||
"global"
|
||||
);
|
||||
|
||||
BE_EXPORT_VARIABLE be_define_const_native_module(global, NULL);
|
|
@ -23,6 +23,11 @@
|
|||
|
||||
#define retreg(vm) ((vm)->cf->func)
|
||||
|
||||
struct solidfuncinfo {
|
||||
const char *name;
|
||||
bclosure *function;
|
||||
};
|
||||
|
||||
static void class_init(bvm *vm, bclass *c, const bnfuncinfo *lib)
|
||||
{
|
||||
if (lib) {
|
||||
|
@ -37,13 +42,13 @@ static void class_init(bvm *vm, bclass *c, const bnfuncinfo *lib)
|
|||
}
|
||||
if (lib->function == (bntvfunc) BE_CLOSURE) {
|
||||
/* next section is closures */
|
||||
++lib;
|
||||
while (lib->name) {
|
||||
if (lib->function) { /* method */
|
||||
bstring *s = be_newstr(vm, lib->name);
|
||||
be_closure_method_bind(vm, c, s, (bclosure*) lib->function);
|
||||
struct solidfuncinfo *slib = (struct solidfuncinfo*)++lib;
|
||||
while (slib->name) {
|
||||
if (slib->function) { /* method */
|
||||
bstring *s = be_newstr(vm, slib->name);
|
||||
be_closure_method_bind(vm, c, s, slib->function);
|
||||
}
|
||||
++lib;
|
||||
++slib;
|
||||
}
|
||||
}
|
||||
be_map_release(vm, c->members); /* clear space */
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/********************************************************************
|
||||
** Copyright (c) 2018-2021 Guan Wenliang & Stephan Hadinger
|
||||
** This file is part of the Berry default interpreter.
|
||||
** skiars@qq.com, https://github.com/Skiars/berry
|
||||
** See Copyright Notice in the LICENSE file or at
|
||||
** https://github.com/Skiars/berry/blob/master/LICENSE
|
||||
********************************************************************/
|
||||
#include "be_object.h"
|
||||
#include "be_module.h"
|
||||
#include "be_string.h"
|
||||
#include "be_vector.h"
|
||||
#include "be_class.h"
|
||||
#include "be_debug.h"
|
||||
#include "be_map.h"
|
||||
#include "be_vm.h"
|
||||
#include <string.h>
|
||||
|
||||
#if BE_USE_GLOBAL_MODULE
|
||||
|
||||
#define global(vm) ((vm)->gbldesc.global)
|
||||
|
||||
static void dump_map_keys(bvm *vm, bmap *map)
|
||||
{
|
||||
if (!map) { return; } /* protect agains potential null pointer */
|
||||
bmapnode *node;
|
||||
bmapiter iter = be_map_iter();
|
||||
while ((node = be_map_next(map, &iter)) != NULL) {
|
||||
if (var_isstr(&node->key)) {
|
||||
bstring *s = var_tostr(&node->key);
|
||||
be_pushstring(vm, str(s));
|
||||
be_data_push(vm, -2);
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int m_globals(bvm *vm)
|
||||
{
|
||||
be_newobject(vm, "list");
|
||||
dump_map_keys(vm, global(vm).vtab);
|
||||
be_pop(vm, 1);
|
||||
be_return(vm);
|
||||
}
|
||||
|
||||
static int m_findglobal(bvm *vm)
|
||||
{
|
||||
int top = be_top(vm);
|
||||
if (top >= 1 && be_isstring(vm, 1)) {
|
||||
const char * name = be_tostring(vm, 1);
|
||||
be_getglobal(vm, name);
|
||||
be_return(vm);
|
||||
}
|
||||
be_return_nil(vm);
|
||||
}
|
||||
|
||||
static int m_setglobal(bvm *vm)
|
||||
{
|
||||
int top = be_top(vm);
|
||||
if (top >= 2 && be_isstring(vm, 1)) {
|
||||
const char * name = be_tostring(vm, 1);
|
||||
be_setglobal(vm, name);
|
||||
be_return(vm);
|
||||
}
|
||||
be_return_nil(vm);
|
||||
}
|
||||
|
||||
#if !BE_USE_PRECOMPILED_OBJECT
|
||||
be_native_module_attr_table(global) {
|
||||
be_native_module_function("()", m_globals),
|
||||
be_native_module_function("member", m_findglobal),
|
||||
be_native_module_function("setmember", m_setglobal),
|
||||
};
|
||||
|
||||
be_define_native_module(global, NULL);
|
||||
#else
|
||||
/* @const_object_info_begin
|
||||
module global (scope: global, depend: BE_USE_GLOBAL_MODULE) {
|
||||
(), func(m_globals)
|
||||
member, func(m_findglobal)
|
||||
setmember, func(m_setglobal)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "../generate/be_fixed_global.h"
|
||||
#endif
|
||||
|
||||
#endif /* BE_USE_INTROSPECT_MODULE */
|
|
@ -837,6 +837,18 @@ newframe: /* a new call frame */
|
|||
*v = tmp;
|
||||
dispatch();
|
||||
}
|
||||
/* if it failed, try 'setmeemner' */
|
||||
bvalue *member = be_module_attr(vm, obj, str_literal(vm, "setmember"));
|
||||
if (member && var_basetype(member) == BE_FUNCTION) {
|
||||
bvalue *top = vm->top;
|
||||
top[0] = *member;
|
||||
top[1] = *b; /* move name to argv[0] */
|
||||
top[2] = tmp; /* move value to argv[1] */
|
||||
vm->top += 3; /* prevent collection results */
|
||||
be_dofunc(vm, top, 2); /* call method 'setmember' */
|
||||
vm->top -= 3;
|
||||
dispatch();
|
||||
}
|
||||
}
|
||||
attribute_error(vm, "writable attribute", a, b);
|
||||
dispatch();
|
||||
|
@ -1018,6 +1030,17 @@ newframe: /* a new call frame */
|
|||
ret_native(vm);
|
||||
break;
|
||||
}
|
||||
case BE_MODULE: {
|
||||
bmodule *f = var_toobj(var);
|
||||
bvalue *member = be_module_attr(vm, f, str_literal(vm, "()"));
|
||||
if (member && var_basetype(member) == BE_FUNCTION) {
|
||||
*var = *member;
|
||||
goto recall; /* call '()' method */
|
||||
} else {
|
||||
call_error(vm, var);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
call_error(vm, var);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
#- test module global -#
|
||||
|
||||
def assert_syntax_error(code)
|
||||
try
|
||||
f = compile(code)
|
||||
assert(false, 'unexpected execution flow')
|
||||
except .. as e, m
|
||||
assert(e == 'syntax_error')
|
||||
end
|
||||
end
|
||||
def assert_attribute_error(f)
|
||||
try
|
||||
f()
|
||||
assert(false, 'unexpected execution flow')
|
||||
except .. as e, m
|
||||
assert(e == 'attribute_error')
|
||||
end
|
||||
end
|
||||
def findinlist(l, e)
|
||||
var i
|
||||
for i: 0..size(l)-1
|
||||
if l[i] == e return i end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
#- set the scene -#
|
||||
global_a = 1
|
||||
global_b = "bb"
|
||||
assert(global_a == 1)
|
||||
assert(global_b == "bb")
|
||||
|
||||
assert_syntax_error("c") #- compilation fails because c does not exist -#
|
||||
|
||||
import global
|
||||
|
||||
assert(global.global_a == 1)
|
||||
assert(global.global_b == "bb")
|
||||
|
||||
global.global_c = 3
|
||||
#- now compilation against 'c' global -#
|
||||
f = compile("return global_c")
|
||||
assert(f() == 3)
|
||||
|
||||
#- check that access to non-existent global returns an exception -#
|
||||
assert_attribute_error(/-> global.d)
|
||||
|
||||
#- check the glbal list -#
|
||||
assert(findinlist(global(), 'global_a') != nil)
|
||||
assert(findinlist(global(), 'global_b') != nil)
|
||||
assert(findinlist(global(), 'global_c') != nil)
|
||||
assert(findinlist(global(), 'global_d') == nil)
|
|
@ -0,0 +1,28 @@
|
|||
#- virtual attributes -#
|
||||
class Ta
|
||||
var a, b, virtual_c
|
||||
def init()
|
||||
self.a = 1
|
||||
self.b = 2
|
||||
self.virtual_c = 3
|
||||
end
|
||||
def member(n)
|
||||
if n == 'c' return self.virtual_c end
|
||||
return nil
|
||||
end
|
||||
def setmember(n, v)
|
||||
if n == 'c' self.virtual_c = v return true end
|
||||
return false
|
||||
end
|
||||
end
|
||||
ta = Ta()
|
||||
|
||||
assert(ta.a == 1)
|
||||
assert(ta.b == 2)
|
||||
assert(ta.c == 3)
|
||||
ta.a = 10
|
||||
assert(ta.a == 10)
|
||||
assert(ta.c == 3)
|
||||
ta.c = 30
|
||||
assert(ta.c == 30)
|
||||
assert(ta.virtual_c == 30)
|
Loading…
Reference in New Issue