Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
10 changes: 5 additions & 5 deletions lib/libesp32/berry/src/be_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
28 changes: 23 additions & 5 deletions lib/libesp32/berry/src/be_globallib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
}
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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"
Expand Down
43 changes: 35 additions & 8 deletions lib/libesp32/berry/src/be_var.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions lib/libesp32/berry/src/be_var.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion lib/libesp32/berry/src/be_vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ static void vm_exec(bvm *vm)
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));
Expand Down