Berry 'global.undef()' to undefine a global variable (#23073)

This commit is contained in:
s-hadinger 2025-02-26 15:30:04 +01:00 committed by GitHub
parent e92e411040
commit 9a98db9773
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 66 additions and 19 deletions

View File

@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file.
- Allow acl in mqtt when client certificate is in use with `#define USE_MQTT_CLIENT_CERT` (#22998)
- Berry `tasmota.when_network_up()` and simplified Matter using it (#23057)
- Berry `introspect.solidified()` to know if a Berry object is solidified or in RAM (#23063)
- Berry `global.undef()` to undefine a global variable
### Breaking Changed

View File

@ -82,8 +82,8 @@ BERRY_API void be_regfunc(bvm *vm, const char *name, bntvfunc f)
bstring *s = be_newstr(vm, name);
#if !BE_USE_PRECOMPILED_OBJECT
int idx = be_builtin_find(vm, s);
be_assert(idx == -1);
if (idx == -1) { /* new function */
be_assert(idx < 0);
if (idx < 0) { /* new function */
idx = be_builtin_new(vm, s);
#else
int idx = be_global_find(vm, s);
@ -102,8 +102,8 @@ BERRY_API void be_regclass(bvm *vm, const char *name, const bnfuncinfo *lib)
bstring *s = be_newstr(vm, name);
#if !BE_USE_PRECOMPILED_OBJECT
int idx = be_builtin_find(vm, s);
be_assert(idx == -1);
if (idx == -1) { /* new function */
be_assert(idx < 0);
if (idx < 0) { /* new function */
idx = be_builtin_new(vm, s);
#else
int idx = be_global_find(vm, s);
@ -599,7 +599,7 @@ BERRY_API bbool be_getglobal(bvm *vm, const char *name)
{
int idx = be_global_find(vm, be_newstr(vm, name));
bvalue *top = be_incrtop(vm);
if (idx > -1) {
if (idx >= 0) {
*top = *be_global_var(vm, idx);
return btrue;
}

View File

@ -27,10 +27,14 @@ static void dump_map_keys(bvm *vm, bmap *map)
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);
/* check if the global was not undefined/removed */
int idx = var_toidx(&node->value);
if (idx >= 0) { /* the key is present in global, and the index is valid */
bstring *s = var_tostr(&node->key);
be_pushstring(vm, str(s));
be_data_push(vm, -2);
be_pop(vm, 1);
}
}
}
}
@ -49,7 +53,7 @@ static int m_contains(bvm *vm)
if (top >= 1 && be_isstring(vm, 1)) {
const char * name = be_tostring(vm, 1);
int idx = be_global_find(vm, be_newstr(vm, name));
be_pushbool(vm, idx > -1);
be_pushbool(vm, idx >= 0);
be_return(vm);
}
be_return_nil(vm);
@ -76,12 +80,25 @@ static int m_setglobal(bvm *vm)
be_return_nil(vm);
}
/* Remove a global variable from global scope */
/* Internally the global name cannot be removed but it's value is replaced with BE_NONE */
/* and global function pretend that BE_NONE is equivalent to the name being absent */
static int m_undef(bvm *vm)
{
int top = be_top(vm);
if (top >= 1 && be_isstring(vm, 1)) {
be_global_undef(vm, be_newstr(vm, be_tostring(vm, 1)));
}
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("contains", m_contains),
be_native_module_function("member", m_findglobal),
be_native_module_function("setmember", m_setglobal),
be_native_module_function("undef", m_undef),
};
be_define_native_module(global, NULL);
@ -92,6 +109,7 @@ module global (scope: global, depend: BE_USE_GLOBAL_MODULE) {
contains, func(m_contains)
member, func(m_findglobal)
setmember, func(m_setglobal)
undef, func(m_undef)
}
@const_object_info_end */
#include "../generate/be_fixed_global.h"

View File

@ -67,19 +67,39 @@ static int global_find(bvm *vm, bstring *name)
{
bvalue *res = be_map_findstr(vm, global(vm).vtab, name);
if (res) {
return var_toidx(res) + be_builtin_count(vm);
int idx = var_toidx(res);
if (idx >= 0) {
return idx + be_builtin_count(vm);
} else {
return idx; /* the global does not exist (-1) or was underfined (< -1)*/
}
}
return -1; /* not found */
}
bbool be_global_undef(bvm *vm, bstring *name)
{
int idx = global_find(vm, name);
if (idx >= 0) {
bvalue *desc = be_map_findstr(vm, global(vm).vtab, name);
int index = var_toidx(desc);
var_setint(desc, -index - 2); /* negate the index to mark it as undefined */
bvalue* val = be_vector_at(&global(vm).vlist, index);
var_setnil(val);
return btrue;
}
return bfalse;
}
int be_global_find(bvm *vm, bstring *name)
{
int res = global_find(vm, name);
int res = global_find(vm, name); /* returns negative if not found, -1 if does not exist, < -1 if existed but undefined */
if (res < 0) {
res = be_builtin_find(vm, name);
res = be_builtin_find(vm, name); /* returns -1 if not found */
}
if (res < 0) {
res = global_native_class_find(vm, name);
res = global_native_class_find(vm, name); /* returns -1 if not found */
}
return res;
}
@ -97,11 +117,18 @@ static int global_new_anonymous(bvm *vm)
int be_global_new(bvm *vm, bstring *name)
{
int idx = global_find(vm, name);
if (idx == -1) {
if (idx < 0) {
bvalue *desc;
idx = global_new_anonymous(vm);
desc = be_map_insertstr(vm, global(vm).vtab, name, NULL);
var_setint(desc, idx);
if (idx == -1) {
idx = global_new_anonymous(vm);
desc = be_map_insertstr(vm, global(vm).vtab, name, NULL);
var_setint(desc, idx);
} else {
/* the global exists but was undefined */
idx = -idx - 2;
desc = be_map_findstr(vm, global(vm).vtab, name);
var_setint(desc, idx);
}
idx += be_builtin_count(vm);
}
return idx;

View File

@ -20,6 +20,7 @@ void be_globalvar_init(bvm *vm);
void be_globalvar_deinit(bvm *vm);
int be_global_find(bvm *vm, bstring *name);
int be_global_new(bvm *vm, bstring *name);
bbool be_global_undef(bvm *vm, bstring *name);
bvalue* be_global_var(bvm *vm, int index);
void be_global_release_space(bvm *vm);
int be_builtin_find(bvm *vm, bstring *name);

View File

@ -591,7 +591,7 @@ newframe: /* a new call frame */
if (var_isstr(b)) {
bstring *name = var_tostr(b);
int idx = be_global_find(vm, name);
if (idx > -1) {
if (idx >= 0) {
*v = *be_global_var(vm, idx);
} else {
vm_error(vm, "attribute_error", "'%s' undeclared", str(name));