mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-28 05:06:32 +00:00
Berry 'global.undef()' to undefine a global variable (#23073)
This commit is contained in:
parent
e92e411040
commit
9a98db9773
@ -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)
|
- 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 `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 `introspect.solidified()` to know if a Berry object is solidified or in RAM (#23063)
|
||||||
|
- Berry `global.undef()` to undefine a global variable
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
|
|
||||||
|
@ -82,8 +82,8 @@ BERRY_API void be_regfunc(bvm *vm, const char *name, bntvfunc f)
|
|||||||
bstring *s = be_newstr(vm, name);
|
bstring *s = be_newstr(vm, name);
|
||||||
#if !BE_USE_PRECOMPILED_OBJECT
|
#if !BE_USE_PRECOMPILED_OBJECT
|
||||||
int idx = be_builtin_find(vm, s);
|
int idx = be_builtin_find(vm, s);
|
||||||
be_assert(idx == -1);
|
be_assert(idx < 0);
|
||||||
if (idx == -1) { /* new function */
|
if (idx < 0) { /* new function */
|
||||||
idx = be_builtin_new(vm, s);
|
idx = be_builtin_new(vm, s);
|
||||||
#else
|
#else
|
||||||
int idx = be_global_find(vm, s);
|
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);
|
bstring *s = be_newstr(vm, name);
|
||||||
#if !BE_USE_PRECOMPILED_OBJECT
|
#if !BE_USE_PRECOMPILED_OBJECT
|
||||||
int idx = be_builtin_find(vm, s);
|
int idx = be_builtin_find(vm, s);
|
||||||
be_assert(idx == -1);
|
be_assert(idx < 0);
|
||||||
if (idx == -1) { /* new function */
|
if (idx < 0) { /* new function */
|
||||||
idx = be_builtin_new(vm, s);
|
idx = be_builtin_new(vm, s);
|
||||||
#else
|
#else
|
||||||
int idx = be_global_find(vm, s);
|
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));
|
int idx = be_global_find(vm, be_newstr(vm, name));
|
||||||
bvalue *top = be_incrtop(vm);
|
bvalue *top = be_incrtop(vm);
|
||||||
if (idx > -1) {
|
if (idx >= 0) {
|
||||||
*top = *be_global_var(vm, idx);
|
*top = *be_global_var(vm, idx);
|
||||||
return btrue;
|
return btrue;
|
||||||
}
|
}
|
||||||
|
@ -27,12 +27,16 @@ static void dump_map_keys(bvm *vm, bmap *map)
|
|||||||
bmapiter iter = be_map_iter();
|
bmapiter iter = be_map_iter();
|
||||||
while ((node = be_map_next(map, &iter)) != NULL) {
|
while ((node = be_map_next(map, &iter)) != NULL) {
|
||||||
if (var_isstr(&node->key)) {
|
if (var_isstr(&node->key)) {
|
||||||
|
/* 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);
|
bstring *s = var_tostr(&node->key);
|
||||||
be_pushstring(vm, str(s));
|
be_pushstring(vm, str(s));
|
||||||
be_data_push(vm, -2);
|
be_data_push(vm, -2);
|
||||||
be_pop(vm, 1);
|
be_pop(vm, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int m_globals(bvm *vm)
|
static int m_globals(bvm *vm)
|
||||||
@ -49,7 +53,7 @@ static int m_contains(bvm *vm)
|
|||||||
if (top >= 1 && be_isstring(vm, 1)) {
|
if (top >= 1 && be_isstring(vm, 1)) {
|
||||||
const char * name = be_tostring(vm, 1);
|
const char * name = be_tostring(vm, 1);
|
||||||
int idx = be_global_find(vm, be_newstr(vm, name));
|
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(vm);
|
||||||
}
|
}
|
||||||
be_return_nil(vm);
|
be_return_nil(vm);
|
||||||
@ -76,12 +80,25 @@ static int m_setglobal(bvm *vm)
|
|||||||
be_return_nil(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
|
#if !BE_USE_PRECOMPILED_OBJECT
|
||||||
be_native_module_attr_table(global) {
|
be_native_module_attr_table(global) {
|
||||||
be_native_module_function("()", m_globals),
|
be_native_module_function("()", m_globals),
|
||||||
be_native_module_function("contains", m_contains),
|
be_native_module_function("contains", m_contains),
|
||||||
be_native_module_function("member", m_findglobal),
|
be_native_module_function("member", m_findglobal),
|
||||||
be_native_module_function("setmember", m_setglobal),
|
be_native_module_function("setmember", m_setglobal),
|
||||||
|
be_native_module_function("undef", m_undef),
|
||||||
};
|
};
|
||||||
|
|
||||||
be_define_native_module(global, NULL);
|
be_define_native_module(global, NULL);
|
||||||
@ -92,6 +109,7 @@ module global (scope: global, depend: BE_USE_GLOBAL_MODULE) {
|
|||||||
contains, func(m_contains)
|
contains, func(m_contains)
|
||||||
member, func(m_findglobal)
|
member, func(m_findglobal)
|
||||||
setmember, func(m_setglobal)
|
setmember, func(m_setglobal)
|
||||||
|
undef, func(m_undef)
|
||||||
}
|
}
|
||||||
@const_object_info_end */
|
@const_object_info_end */
|
||||||
#include "../generate/be_fixed_global.h"
|
#include "../generate/be_fixed_global.h"
|
||||||
|
@ -67,19 +67,39 @@ static int global_find(bvm *vm, bstring *name)
|
|||||||
{
|
{
|
||||||
bvalue *res = be_map_findstr(vm, global(vm).vtab, name);
|
bvalue *res = be_map_findstr(vm, global(vm).vtab, name);
|
||||||
if (res) {
|
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 */
|
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 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) {
|
if (res < 0) {
|
||||||
res = be_builtin_find(vm, name);
|
res = be_builtin_find(vm, name); /* returns -1 if not found */
|
||||||
}
|
}
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
res = global_native_class_find(vm, name);
|
res = global_native_class_find(vm, name); /* returns -1 if not found */
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -97,11 +117,18 @@ static int global_new_anonymous(bvm *vm)
|
|||||||
int be_global_new(bvm *vm, bstring *name)
|
int be_global_new(bvm *vm, bstring *name)
|
||||||
{
|
{
|
||||||
int idx = global_find(vm, name);
|
int idx = global_find(vm, name);
|
||||||
if (idx == -1) {
|
if (idx < 0) {
|
||||||
bvalue *desc;
|
bvalue *desc;
|
||||||
|
if (idx == -1) {
|
||||||
idx = global_new_anonymous(vm);
|
idx = global_new_anonymous(vm);
|
||||||
desc = be_map_insertstr(vm, global(vm).vtab, name, NULL);
|
desc = be_map_insertstr(vm, global(vm).vtab, name, NULL);
|
||||||
var_setint(desc, idx);
|
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);
|
idx += be_builtin_count(vm);
|
||||||
}
|
}
|
||||||
return idx;
|
return idx;
|
||||||
|
@ -20,6 +20,7 @@ void be_globalvar_init(bvm *vm);
|
|||||||
void be_globalvar_deinit(bvm *vm);
|
void be_globalvar_deinit(bvm *vm);
|
||||||
int be_global_find(bvm *vm, bstring *name);
|
int be_global_find(bvm *vm, bstring *name);
|
||||||
int be_global_new(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);
|
bvalue* be_global_var(bvm *vm, int index);
|
||||||
void be_global_release_space(bvm *vm);
|
void be_global_release_space(bvm *vm);
|
||||||
int be_builtin_find(bvm *vm, bstring *name);
|
int be_builtin_find(bvm *vm, bstring *name);
|
||||||
|
@ -591,7 +591,7 @@ newframe: /* a new call frame */
|
|||||||
if (var_isstr(b)) {
|
if (var_isstr(b)) {
|
||||||
bstring *name = var_tostr(b);
|
bstring *name = var_tostr(b);
|
||||||
int idx = be_global_find(vm, name);
|
int idx = be_global_find(vm, name);
|
||||||
if (idx > -1) {
|
if (idx >= 0) {
|
||||||
*v = *be_global_var(vm, idx);
|
*v = *be_global_var(vm, idx);
|
||||||
} else {
|
} else {
|
||||||
vm_error(vm, "attribute_error", "'%s' undeclared", str(name));
|
vm_error(vm, "attribute_error", "'%s' undeclared", str(name));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user