Berry add module `global`

This commit is contained in:
Stephan Hadinger 2021-05-26 15:53:53 +02:00
parent f49adad496
commit a6591ab6dd
11 changed files with 1601 additions and 1378 deletions

View File

@ -100,7 +100,7 @@ void be_load_driver_i2c_lib(bvm *vm) {
} }
/* @const_object_info_begin /* @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 wire, var
addr, var addr, var
name, var name, var

View File

@ -15,6 +15,7 @@ be_extern_native_module(json);
be_extern_native_module(math); be_extern_native_module(math);
be_extern_native_module(time); be_extern_native_module(time);
be_extern_native_module(os); be_extern_native_module(os);
be_extern_native_module(global);
be_extern_native_module(sys); be_extern_native_module(sys);
be_extern_native_module(debug); be_extern_native_module(debug);
be_extern_native_module(gc); be_extern_native_module(gc);
@ -50,6 +51,9 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = {
#if BE_USE_OS_MODULE #if BE_USE_OS_MODULE
&be_native_module(os), &be_native_module(os),
#endif #endif
#if BE_USE_GLOBAL_MODULE
&be_native_module(global),
#endif
#if BE_USE_SYS_MODULE #if BE_USE_SYS_MODULE
&be_native_module(sys), &be_native_module(sys),
#endif #endif

View File

@ -153,6 +153,7 @@
#define BE_USE_MATH_MODULE 1 #define BE_USE_MATH_MODULE 1
#define BE_USE_TIME_MODULE 0 #define BE_USE_TIME_MODULE 0
#define BE_USE_OS_MODULE 0 #define BE_USE_OS_MODULE 0
#define BE_USE_GLOBAL_MODULE 1
#define BE_USE_SYS_MODULE 0 #define BE_USE_SYS_MODULE 0
#define BE_USE_DEBUG_MODULE 1 #define BE_USE_DEBUG_MODULE 1
#define BE_USE_GC_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

View File

@ -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);

View File

@ -23,6 +23,11 @@
#define retreg(vm) ((vm)->cf->func) #define retreg(vm) ((vm)->cf->func)
struct solidfuncinfo {
const char *name;
bclosure *function;
};
static void class_init(bvm *vm, bclass *c, const bnfuncinfo *lib) static void class_init(bvm *vm, bclass *c, const bnfuncinfo *lib)
{ {
if (lib) { if (lib) {
@ -37,13 +42,13 @@ static void class_init(bvm *vm, bclass *c, const bnfuncinfo *lib)
} }
if (lib->function == (bntvfunc) BE_CLOSURE) { if (lib->function == (bntvfunc) BE_CLOSURE) {
/* next section is closures */ /* next section is closures */
++lib; struct solidfuncinfo *slib = (struct solidfuncinfo*)++lib;
while (lib->name) { while (slib->name) {
if (lib->function) { /* method */ if (slib->function) { /* method */
bstring *s = be_newstr(vm, lib->name); bstring *s = be_newstr(vm, slib->name);
be_closure_method_bind(vm, c, s, (bclosure*) lib->function); be_closure_method_bind(vm, c, s, slib->function);
} }
++lib; ++slib;
} }
} }
be_map_release(vm, c->members); /* clear space */ be_map_release(vm, c->members); /* clear space */

View File

@ -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 */

View File

@ -837,6 +837,18 @@ newframe: /* a new call frame */
*v = tmp; *v = tmp;
dispatch(); 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); attribute_error(vm, "writable attribute", a, b);
dispatch(); dispatch();
@ -1018,6 +1030,17 @@ newframe: /* a new call frame */
ret_native(vm); ret_native(vm);
break; 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: default:
call_error(vm, var); call_error(vm, var);
} }

View File

@ -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)

View File

@ -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)