diff --git a/lib/libesp32/Berry-0.1.10/generate/be_fixed_solidify.h b/lib/libesp32/Berry-0.1.10/generate/be_fixed_solidify.h new file mode 100644 index 000000000..fea7be4ed --- /dev/null +++ b/lib/libesp32/Berry-0.1.10/generate/be_fixed_solidify.h @@ -0,0 +1,17 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(m_libsolidify_map) { + { be_const_key(dump, -1), be_const_func(m_dump) }, +}; + +static be_define_const_map( + m_libsolidify_map, + 1 +); + +static be_define_const_module( + m_libsolidify, + "solidify" +); + +BE_EXPORT_VARIABLE be_define_const_native_module(solidify, NULL); diff --git a/lib/libesp32/Berry-0.1.10/generate/be_fixed_tasmota.h b/lib/libesp32/Berry-0.1.10/generate/be_fixed_tasmota.h new file mode 100644 index 000000000..12eff88ab --- /dev/null +++ b/lib/libesp32/Berry-0.1.10/generate/be_fixed_tasmota.h @@ -0,0 +1,2 @@ +#include "be_constobj.h" + diff --git a/lib/libesp32/Berry-0.1.10/src/be_api.c b/lib/libesp32/Berry-0.1.10/src/be_api.c index dc34b950c..d1232096c 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_api.c +++ b/lib/libesp32/Berry-0.1.10/src/be_api.c @@ -35,6 +35,17 @@ static void class_init(bvm *vm, bclass *c, const bnfuncinfo *lib) } ++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); + } + ++lib; + } + } be_map_release(vm, c->members); /* clear space */ } } @@ -346,6 +357,13 @@ BERRY_API void be_pushvalue(bvm *vm, int index) be_incrtop(vm); } +BERRY_API void be_pushclosure(bvm *vm, void *cl) +{ + bvalue *reg = be_incrtop(vm); + bclosure * closure = (bclosure*) cl; + var_setclosure(reg, closure); +} + BERRY_API void be_pushntvclosure(bvm *vm, bntvfunc f, int nupvals) { /* to create a native closure and then push the top registor, diff --git a/lib/libesp32/Berry-0.1.10/src/be_byteslib.c b/lib/libesp32/Berry-0.1.10/src/be_byteslib.c index 7217c7d75..f26fe1909 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_byteslib.c +++ b/lib/libesp32/Berry-0.1.10/src/be_byteslib.c @@ -32,12 +32,14 @@ typedef struct buf_impl { ** ** Extracted from Tasmota SBuffer lib ********************************************************************/ -static inline uint8_t* buf_get_buf(buf_impl* buf) { +static inline uint8_t* buf_get_buf(buf_impl* buf) +{ return &buf->buf[0]; } // shrink or increase. If increase, fill with zeores. Cannot go beyond `size` -static void buf_set_len(buf_impl* buf, const size_t len) { +static void buf_set_len(buf_impl* buf, const size_t len) +{ uint16_t old_len = buf->len; buf->len = (len <= buf->size) ? len : buf->size; if (old_len < buf->len) { @@ -45,33 +47,41 @@ static void buf_set_len(buf_impl* buf, const size_t len) { } } - -static void buf_set1(buf_impl* buf, const size_t offset, const uint8_t data) { +static void buf_set1(buf_impl* buf, const size_t offset, const uint8_t data) +{ if (offset < buf->len) { buf->buf[offset] = data; } } -static size_t buf_add1(buf_impl* buf, const uint8_t data) { // append 8 bits value + +static size_t buf_add1(buf_impl* buf, const uint8_t data) // append 8 bits value +{ if (buf->len < buf->size) { // do we have room for 1 byte buf->buf[buf->len++] = data; } return buf->len; } -static size_t buf_add2_le(buf_impl* buf, const uint16_t data) { // append 16 bits value + +static size_t buf_add2_le(buf_impl* buf, const uint16_t data) // append 16 bits value +{ if (buf->len < buf->size - 1) { // do we have room for 2 bytes buf->buf[buf->len++] = data; buf->buf[buf->len++] = data >> 8; } return buf->len; } -static size_t buf_add2_be(buf_impl* buf, const uint16_t data) { // append 16 bits value + +static size_t buf_add2_be(buf_impl* buf, const uint16_t data) // append 16 bits value +{ if (buf->len < buf->size - 1) { // do we have room for 2 bytes buf->buf[buf->len++] = data >> 8; buf->buf[buf->len++] = data; } return buf->len; } -static size_t buf_add4_le(buf_impl* buf, const uint32_t data) { // append 32 bits value + +static size_t buf_add4_le(buf_impl* buf, const uint32_t data) // append 32 bits value +{ if (buf->len < buf->size - 3) { // do we have room for 4 bytes buf->buf[buf->len++] = data; buf->buf[buf->len++] = data >> 8; @@ -80,7 +90,9 @@ static size_t buf_add4_le(buf_impl* buf, const uint32_t data) { // app } return buf->len; } -size_t buf_add4_be(buf_impl* buf, const uint32_t data) { // append 32 bits value + +size_t buf_add4_be(buf_impl* buf, const uint32_t data) // append 32 bits value +{ if (buf->len < buf->size - 3) { // do we have room for 4 bytes buf->buf[buf->len++] = data >> 24; buf->buf[buf->len++] = data >> 16; @@ -90,7 +102,8 @@ size_t buf_add4_be(buf_impl* buf, const uint32_t data) { // append 32 return buf->len; } -static size_t buf_add_buf(buf_impl* buf, buf_impl* buf2) { +static size_t buf_add_buf(buf_impl* buf, buf_impl* buf2) +{ if (buf->len + buf2->len <= buf->size) { for (uint32_t i = 0; i < buf2->len; i++) { buf->buf[buf->len++] = buf2->buf[i]; @@ -99,32 +112,40 @@ static size_t buf_add_buf(buf_impl* buf, buf_impl* buf2) { return buf->len; } -static uint8_t buf_get1(buf_impl* buf, int offset) { +static uint8_t buf_get1(buf_impl* buf, int offset) +{ if ((offset >= 0) && (offset < buf->len)) { return buf->buf[offset]; } return 0; } + static uint16_t buf_get2_le(buf_impl* buf, int offset) { if ((offset >= 0) && (offset < buf->len - 1)) { return buf->buf[offset] | (buf->buf[offset+1] << 8); } return 0; } -static uint16_t buf_get2_be(buf_impl* buf, int offset) { + +static uint16_t buf_get2_be(buf_impl* buf, int offset) +{ if (offset < buf->len - 1) { return buf->buf[offset+1] | (buf->buf[offset] << 8); } return 0; } -static uint32_t buf_get4_le(buf_impl* buf, int offset) { + +static uint32_t buf_get4_le(buf_impl* buf, int offset) +{ if ((offset >= 0) && (offset < buf->len - 3)) { return buf->buf[offset] | (buf->buf[offset+1] << 8) | (buf->buf[offset+2] << 16) | (buf->buf[offset+3] << 24); } return 0; } -static uint32_t buf_get4_be(buf_impl* buf, int offset) { + +static uint32_t buf_get4_be(buf_impl* buf, int offset) +{ if (offset < buf->len - 3) { return buf->buf[offset+3] | (buf->buf[offset+2] << 8) | (buf->buf[offset+1] << 16) | (buf->buf[offset] << 24); @@ -133,7 +154,8 @@ static uint32_t buf_get4_be(buf_impl* buf, int offset) { } // nullptr accepted -static bbool buf_equals(buf_impl* buf1, buf_impl* buf2) { +static bbool buf_equals(buf_impl* buf1, buf_impl* buf2) +{ if (buf1 == buf2) { return btrue; } if (!buf1 || !buf2) { return bfalse; } // at least one buf is not empty // we know that both buf1 and buf2 are non-null @@ -145,7 +167,8 @@ static bbool buf_equals(buf_impl* buf1, buf_impl* buf2) { return btrue; } -static uint8_t asc2byte(char chr) { +static uint8_t asc2byte(char chr) +{ uint8_t rVal = 0; if (isdigit(chr)) { rVal = chr - '0'; } else if (chr >= 'A' && chr <= 'F') { rVal = chr + 10 - 'A'; } @@ -153,7 +176,8 @@ static uint8_t asc2byte(char chr) { return rVal; } // does not check if there is enough room before hand, truncated if buffer too small -static void buf_add_hex(buf_impl* buf, const char *hex, size_t len) { +static void buf_add_hex(buf_impl* buf, const char *hex, size_t len) +{ uint8_t val; for (; len > 1; len -= 2) { val = asc2byte(*hex++) << 4; @@ -166,7 +190,8 @@ static void buf_add_hex(buf_impl* buf, const char *hex, size_t len) { ** Wrapping into lib ********************************************************************/ // typedef int (*bntvfunc)(bvm*); /* native function pointer */ -int free_bytes_buf(bvm* vm) { +int free_bytes_buf(bvm* vm) +{ int argc = be_top(vm); if (argc > 0) { buf_impl * buf = (buf_impl*) be_tocomptr(vm, 1); @@ -285,9 +310,9 @@ static int m_tostring(bvm *vm) size_t hex_len = len * 2 + 5 + 2 + 2 + 1; /* reserve size for `bytes("")\0` - 9 chars */ char * hex_out = be_pushbuffer(vm, hex_len); - size_t l = strlcpy(hex_out, "bytes('", hex_len); + size_t l = be_strlcpy(hex_out, "bytes('", hex_len); l += tohex(&hex_out[l], hex_len - l, buf_get_buf(buf), buf->len); - l += strlcpy(&hex_out[l], "')", hex_len - l); + l += be_strlcpy(&hex_out[l], "')", hex_len - l); be_pushnstring(vm, hex_out, l); /* make escape string from buffer */ be_remove(vm, -2); /* remove buffer */ @@ -303,6 +328,7 @@ static int m_asstring(bvm *vm) be_pushnstring(vm, (const char*) buf_get_buf(buf), buf->len); be_return(vm); } + static int m_fromstring(bvm *vm) { int argc = be_top(vm); @@ -395,7 +421,6 @@ static int m_get(bvm *vm) be_return_nil(vm); } - static int m_setitem(bvm *vm) { int argc = be_top(vm); diff --git a/lib/libesp32/Berry-0.1.10/src/be_class.c b/lib/libesp32/Berry-0.1.10/src/be_class.c index 71e42c787..ed475af7e 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_class.c +++ b/lib/libesp32/Berry-0.1.10/src/be_class.c @@ -59,8 +59,10 @@ int be_class_attribute(bvm *vm, bclass *c, bstring *attr) void be_member_bind(bvm *vm, bclass *c, bstring *name) { bvalue *attr; + set_fixed(name); check_members(vm, c); attr = be_map_insertstr(vm, c->members, name, NULL); + restore_fixed(name); attr->v.i = c->nvar++; attr->type = MT_VARIABLE; } @@ -69,8 +71,10 @@ void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p) { bclosure *cl; bvalue *attr; + set_fixed(name); check_members(vm, c); attr = be_map_insertstr(vm, c->members, name, NULL); + restore_fixed(name); var_setnil(attr); cl = be_newclosure(vm, p->nupvals); cl->proto = p; @@ -80,12 +84,23 @@ void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p) void be_prim_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f) { bvalue *attr; + set_fixed(name); check_members(vm, c); attr = be_map_insertstr(vm, c->members, name, NULL); + restore_fixed(name); attr->v.nf = f; attr->type = MT_PRIMMETHOD; } +void be_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl) +{ + bvalue *attr; + check_members(vm, c); + attr = be_map_insertstr(vm, c->members, name, NULL); + attr->v.gc = (bgcobject*) cl; + attr->type = MT_METHOD; +} + /* get the closure method count that need upvalues */ int be_class_closure_count(bclass *c) { diff --git a/lib/libesp32/Berry-0.1.10/src/be_class.h b/lib/libesp32/Berry-0.1.10/src/be_class.h index ac2e68c79..34be6943a 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_class.h +++ b/lib/libesp32/Berry-0.1.10/src/be_class.h @@ -52,6 +52,7 @@ int be_class_attribute(bvm *vm, bclass *c, bstring *attr); void be_member_bind(bvm *vm, bclass *c, bstring *name); void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p); void be_prim_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f); +void be_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl); int be_class_closure_count(bclass *c); void be_class_upvalue_init(bvm *vm, bclass *c); bbool be_class_newobj(bvm *vm, bclass *c, bvalue *argv, int argc); diff --git a/lib/libesp32/Berry-0.1.10/src/be_debug.c b/lib/libesp32/Berry-0.1.10/src/be_debug.c index b50a27b02..f46446199 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_debug.c +++ b/lib/libesp32/Berry-0.1.10/src/be_debug.c @@ -46,7 +46,7 @@ static const char* opc2str(bopcode op) return op < array_count(opc_tab) ? opc_tab[op] : "ERROP"; } -static void print_inst(binstruction ins, int pc) +void be_print_inst(binstruction ins, int pc) { char __lbuf[INST_BUF_SIZE]; bopcode op = IGET_OP(ins); @@ -145,7 +145,7 @@ void be_dumpclosure(bclosure *cl) logfmt("; line %d\n", (++lineinfo)->linenumber); } #endif - print_inst(*code++, pc); + be_print_inst(*code++, pc); } } #endif diff --git a/lib/libesp32/Berry-0.1.10/src/be_debug.h b/lib/libesp32/Berry-0.1.10/src/be_debug.h index 13ec28936..0956e8f8e 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_debug.h +++ b/lib/libesp32/Berry-0.1.10/src/be_debug.h @@ -21,4 +21,8 @@ void be_callhook(bvm *vm, int mask); bbool be_debug_varname(bvm *vm, int level, int index); bbool be_debug_upvname(bvm *vm, int level, int index); +#if BE_USE_DEBUG_MODULE +void be_print_inst(binstruction ins, int pc); +#endif + #endif diff --git a/lib/libesp32/Berry-0.1.10/src/be_gc.c b/lib/libesp32/Berry-0.1.10/src/be_gc.c index 8993cbaf7..fca6ad45d 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_gc.c +++ b/lib/libesp32/Berry-0.1.10/src/be_gc.c @@ -120,6 +120,20 @@ void be_gc_unfix(bvm *vm, bgcobject *obj) } } +bbool be_gc_fix_set(bvm *vm, bgcobject *obj, bbool fix) +{ + (void)vm; + bbool was_fixed = gc_isfixed(obj); + if (!gc_isconst(obj)) { + if (fix) { + gc_setfixed(obj); + } else { + gc_clearfixed(obj); + } + } + return was_fixed; +} + static void mark_gray(bvm *vm, bgcobject *obj) { if (obj && gc_iswhite(obj) && !gc_isconst(obj)) { @@ -285,6 +299,9 @@ static void free_proto(bvm *vm, bgcobject *obj) be_free(vm, proto->code, proto->codesize * sizeof(binstruction)); #if BE_DEBUG_RUNTIME_INFO be_free(vm, proto->lineinfo, proto->nlineinfo * sizeof(blineinfo)); +#endif +#if BE_DEBUG_VAR_INFO + be_free(vm, proto->varinfo, proto->nvarinfo * sizeof(bvarinfo)); #endif be_free(vm, proto, sizeof(bproto)); } @@ -489,9 +506,15 @@ static void reset_fixedlist(bvm *vm) void be_gc_auto(bvm *vm) { +#if BE_USE_DEBUG_GC + if (vm->gc.status & GC_PAUSE) { /* force gc each time it's possible */ + be_gc_collect(vm); + } +#else if (vm->gc.status & GC_PAUSE && vm->gc.usage > vm->gc.threshold) { be_gc_collect(vm); } +#endif } size_t be_gc_memcount(bvm *vm) @@ -505,7 +528,8 @@ void be_gc_collect(bvm *vm) return; /* the GC cannot run for some reason */ } #if BE_USE_OBSERVABILITY_HOOK - if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_GC_START, vm->gc.usage); + if (vm->obshook != NULL) + (*vm->obshook)(vm, BE_OBS_GC_START, vm->gc.usage); #endif /* step 1: set root-set reference objects to unscanned */ premark_internal(vm); /* object internal the VM */ @@ -524,6 +548,7 @@ void be_gc_collect(bvm *vm) /* step 5: calculate the next GC threshold */ vm->gc.threshold = next_threshold(vm->gc); #if BE_USE_OBSERVABILITY_HOOK - if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage); + if (vm->obshook != NULL) + (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage); #endif } diff --git a/lib/libesp32/Berry-0.1.10/src/be_gc.h b/lib/libesp32/Berry-0.1.10/src/be_gc.h index 16ca7e766..b1b204c13 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_gc.h +++ b/lib/libesp32/Berry-0.1.10/src/be_gc.h @@ -49,6 +49,9 @@ if (!gc_isconst(o)) { \ #define be_isgcobj(o) be_isgctype(var_type(o)) #define be_gcnew(v, t, s) be_newgcobj((v), (t), sizeof(s)) +#define set_fixed(s) bbool _was_fixed = be_gc_fix_set(vm, cast(bgcobject*, (s)), 1) +#define restore_fixed(s) be_gc_fix_set(vm, cast(bgcobject*, (s)), _was_fixed); + /* the GC mark uses bit4:0 of the `object->marked` field, * so other bits can be used for special flags (ex-mark). */ typedef enum { @@ -68,6 +71,7 @@ bgcobject *be_newgcobj(bvm *vm, int type, size_t size); bgcobject* be_gc_newstr(bvm *vm, size_t size, int islong); void be_gc_fix(bvm *vm, bgcobject *obj); void be_gc_unfix(bvm *vm, bgcobject *obj); +bbool be_gc_fix_set(bvm *vm, bgcobject *obj, bbool fix); void be_gc_collect(bvm *vm); void be_gc_auto(bvm *vm); diff --git a/lib/libesp32/Berry-0.1.10/src/be_libs.c b/lib/libesp32/Berry-0.1.10/src/be_libs.c index 5dc77ea85..a4c774df4 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_libs.c +++ b/lib/libesp32/Berry-0.1.10/src/be_libs.c @@ -12,9 +12,7 @@ extern void be_load_listlib(bvm *vm); extern void be_load_maplib(bvm *vm); extern void be_load_rangelib(bvm *vm); extern void be_load_filelib(bvm *vm); - -extern void be_load_tasmota_ntvlib(bvm *vm); -extern void be_load_wirelib(bvm *vm); +extern void be_load_byteslib(bvm *vm); void be_loadlibs(bvm *vm) { @@ -26,6 +24,4 @@ void be_loadlibs(bvm *vm) be_load_filelib(vm); be_load_byteslib(vm); #endif - be_load_tasmota_ntvlib(vm); - be_load_wirelib(vm); } diff --git a/lib/libesp32/Berry-0.1.10/src/be_map.c b/lib/libesp32/Berry-0.1.10/src/be_map.c index 4a7d072ca..a11614680 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_map.c +++ b/lib/libesp32/Berry-0.1.10/src/be_map.c @@ -315,7 +315,10 @@ bvalue* be_map_insertstr(bvm *vm, bmap *map, bstring *key, bvalue *value) { bvalue v; var_setstr(&v, key); - return be_map_insert(vm, map, &v, value); + set_fixed(key); + bvalue * r = be_map_insert(vm, map, &v, value); + restore_fixed(key); + return r; } void be_map_removestr(bvm *vm, bmap *map, bstring *key) diff --git a/lib/libesp32/Berry-0.1.10/src/be_mem.c b/lib/libesp32/Berry-0.1.10/src/be_mem.c index 7047f14e5..9cfe364df 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_mem.c +++ b/lib/libesp32/Berry-0.1.10/src/be_mem.c @@ -10,6 +10,7 @@ #include "be_vm.h" #include "be_gc.h" #include +#include #define GC_ALLOC (1 << 2) /* GC in alloc */ @@ -53,6 +54,10 @@ static void* _realloc(void *ptr, size_t old_size, size_t new_size) return malloc(new_size); } be_assert(new_size == 0); + +#if BE_USE_DEBUG_GC + memset(ptr, 0xFF, old_size); /* fill the structure with invalid pointers */ +#endif free(ptr); return NULL; } diff --git a/lib/libesp32/Berry-0.1.10/src/be_solidifylib.c b/lib/libesp32/Berry-0.1.10/src/be_solidifylib.c new file mode 100644 index 000000000..cd355bc3d --- /dev/null +++ b/lib/libesp32/Berry-0.1.10/src/be_solidifylib.c @@ -0,0 +1,232 @@ +/******************************************************************** +** Copyright (c) 2018-2020 Guan Wenliang +** 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 "be_decoder.h" +#include +#include + +#if BE_USE_SOLIDIFY_MODULE + +#ifndef INST_BUF_SIZE +#define INST_BUF_SIZE 96 +#endif + +#define logbuf(...) snprintf(__lbuf, sizeof(__lbuf), __VA_ARGS__) + +#define logfmt(...) \ + do { \ + char __lbuf[INST_BUF_SIZE]; \ + logbuf(__VA_ARGS__); \ + be_writestring(__lbuf); \ + } while (0) + +/* output only valid types for ktab, or NULL */ +static const char * m_type_ktab(int type) +{ + switch (type){ + case BE_NIL: return "BE_NIL"; + case BE_INT: return "BE_INT"; + case BE_REAL: return "BE_REAL"; + case BE_BOOL: return "BE_BOOL"; + case BE_STRING: return "BE_STRING"; + default: return NULL; + } +} + +static void m_solidify_closure(bvm *vm, bclosure *cl, int builtins) +{ + bproto *pr = cl->proto; + const char * func_name = str(pr->name); + const char * func_source = str(pr->source); + // logfmt("// == builtin_count %i\n", builtins); + + // logfmt("// type %i, ", cl->type); + // logfmt("// marked %i, ", cl->marked); + // logfmt("// nupvals %i\n", cl->nupvals); + + // logfmt("// PROTO:\n"); + // logfmt("// type %i, ", pr->type); + // logfmt("// marked %i, ", pr->marked); + // logfmt("// nstack %i, ", pr->nstack); + // logfmt("// argcs %i, ", pr->argc); + // // logfmt("// varg %i\n", pr->varg); + + // logfmt("// gray %p\n", (void*)pr->gray); + // logfmt("// upvals %p\n", (void*)pr->upvals); + // logfmt("// proto_tab %p (%i)\n", (void*)pr->ptab, pr->nproto); + + // logfmt("// name %s\n", str(pr->name)); + // logfmt("// source %s\n", str(pr->source)); + + // logfmt("\n"); + + // logfmt("// ktab %p (%i)\n", (void*)pr->ktab, pr->nconst); + // for (int i = 0; i < pr->nconst; i++) { + // logfmt("// const[%i] type %i (%s) %p", i, pr->ktab[i].type, be_vtype2str(&pr->ktab[i]), pr->ktab[i].v.p); + // if (pr->ktab[i].type == BE_STRING) { + // logfmt(" = '%s'", str(pr->ktab[i].v.s)); + // } + // logfmt("\n"); + // } + + logfmt("\n"); + logfmt("/********************************************************************\n"); + logfmt("** Solidified function: %s\n", func_name); + logfmt("********************************************************************/\n\n"); + + /* create static strings for name and source */ + logfmt("be_define_local_const_str(%s_str_name, \"%s\", %i, 0, %u, 0);\n", + func_name, func_name, be_strhash(pr->name), str_len(pr->name)); + logfmt("be_define_local_const_str(%s_str_source, \"%s\", %i, 0, %u, 0);\n", + func_name, func_source, be_strhash(pr->source), str_len(pr->source)); + + /* create static strings first */ + for (int i = 0; i < pr->nconst; i++) { + if (pr->ktab[i].type == BE_STRING) { + logfmt("be_define_local_const_str(%s_str_%i, \"", + func_name, i); + be_writestring(str(pr->ktab[i].v.s)); + size_t len = strlen(str(pr->ktab[i].v.s)); + if (len >= 255) { + be_raise(vm, "internal_error", "Strings greater than 255 chars not supported yet"); + } + logfmt("\", %i, 0, %zu, 0);\n", be_strhash(pr->ktab[i].v.s), len >= 255 ? 255 : len); + } + } + logfmt("\n"); + + logfmt("static const bvalue %s_ktab[%i] = {\n", func_name, pr->nconst); + for (int k = 0; k < pr->nconst; k++) { + int type = pr->ktab[k].type; + const char *type_name = m_type_ktab(type); + if (type_name == NULL) { + char error[64]; + snprintf(error, sizeof(error), "Unsupported type in function constants: %i", type); + be_raise(vm, "internal_error", error); + } + if (type == BE_STRING) { + logfmt(" { { .s=be_local_const_str(%s_str_%i) }, %s},\n", func_name, k, type_name); + } else if (type == BE_INT) { + logfmt(" { { .i=%" BE_INT_FMTLEN "i }, %s},\n", pr->ktab[k].v.i, type_name); + } else if (type == BE_REAL) { +#if BE_USE_SINGLE_FLOAT + logfmt(" { { .p=(void*)0x%08X }, %s},\n", (uint32_t) pr->ktab[k].v.p, type_name); +#else + logfmt(" { { .p=(void*)0x%016llX }, %s},\n", (uint64_t) pr->ktab[k].v.p, type_name); +#endif + } else if (type == BE_BOOL) { + logfmt(" { { .b=%i }, %s},\n", pr->ktab[k].v.b, type_name); + } + } + logfmt("};\n\n"); + + logfmt("static const uint32_t %s_code[%i] = {\n", func_name, pr->codesize); + for (int pc = 0; pc < pr->codesize; pc++) { + uint32_t ins = pr->code[pc]; + logfmt(" 0x%04X, //", ins); + be_print_inst(ins, pc); + bopcode op = IGET_OP(ins); + if (op == OP_GETGBL || op == OP_SETGBL) { + // check if the global is in built-ins + int glb = IGET_Bx(ins); + if (glb > builtins) { + // not supported + logfmt("\n===== unsupported global G%d\n", glb); + be_raise(vm, "internal_error", "Unsupported access to non-builtin global"); + } + } + } + logfmt("};\n\n"); + + logfmt("static const bproto %s_proto = {\n", func_name); + // bcommon_header + logfmt(" NULL, // bgcobject *next\n"); + logfmt(" %i, // type\n", pr->type); + logfmt(" GC_CONST, // marked\n"); + // + logfmt(" %i, // nstack\n", pr->nstack); + logfmt(" %i, // nupvals\n", pr->nupvals); + logfmt(" %i, // argc\n", pr->argc); + logfmt(" %i, // varg\n", pr->varg); + if (pr->nproto > 0) { + be_raise(vm, "internal_error", "unsupported non-null proto list"); + } + logfmt(" NULL, // bgcobject *gray\n"); + logfmt(" NULL, // bupvaldesc *upvals\n"); + logfmt(" (bvalue*) &%s_ktab, // ktab\n", func_name); + logfmt(" NULL, // bproto **ptab\n"); + logfmt(" (binstruction*) &%s_code, // code\n", func_name); + logfmt(" be_local_const_str(%s_str_name), // name\n", func_name); + logfmt(" %i, // codesize\n", pr->codesize); + logfmt(" %i, // nconst\n", pr->nconst); + logfmt(" %i, // nproto\n", pr->nproto); + logfmt(" be_local_const_str(%s_str_source), // source\n", func_name); + // + logfmt("#if BE_DEBUG_RUNTIME_INFO /* debug information */\n"); + logfmt(" NULL, // lineinfo\n"); + logfmt(" 0, // nlineinfo\n"); + logfmt("#endif\n"); + logfmt("#if BE_DEBUG_VAR_INFO\n"); + logfmt(" NULL, // varinfo\n"); + logfmt(" 0, // nvarinfo\n"); + logfmt("#endif\n"); + logfmt("};\n\n"); + + // closure + logfmt("static const bclosure %s_closure = {\n", func_name); + // bcommon_header + logfmt(" NULL, // bgcobject *next\n"); + logfmt(" %i, // type\n", cl->type); + logfmt(" GC_CONST, // marked\n"); + // + logfmt(" %i, // nupvals\n", cl->nupvals); + logfmt(" NULL, // bgcobject *gray\n"); + logfmt(" (bproto*) &%s_proto, // proto\n", func_name); + logfmt(" { NULL } // upvals\n"); + logfmt("};\n\n"); + + logfmt("/*******************************************************************/\n\n"); +} + +#define be_builtin_count(vm) \ + be_vector_count(&(vm)->gbldesc.builtin.vlist) + +static int m_dump(bvm *vm) +{ + if (be_top(vm) >= 1) { + bvalue *v = be_indexof(vm, 1); + if (var_isclosure(v)) { + m_solidify_closure(vm, var_toobj(v), be_builtin_count(vm)); + } + } + be_return_nil(vm); +} + +#if !BE_USE_PRECOMPILED_OBJECT +be_native_module_attr_table(solidify) { + be_native_module_function("dump", m_dump), +}; + +be_define_native_module(solidify, NULL); +#else +/* @const_object_info_begin +module solidify (scope: global, depend: BE_USE_SOLIDIFY_MODULE) { + dump, func(m_dump) +} +@const_object_info_end */ +#include "../generate/be_fixed_solidify.h" +#endif + +#endif /* BE_USE_SOLIFIDY_MODULE */ diff --git a/lib/libesp32/Berry-0.1.10/src/be_string.c b/lib/libesp32/Berry-0.1.10/src/be_string.c index db7dcaebf..d9685968f 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_string.c +++ b/lib/libesp32/Berry-0.1.10/src/be_string.c @@ -14,7 +14,7 @@ #define next(_s) cast(void*, cast(bstring*, (_s)->next)) #define sstr(_s) cast(char*, cast(bsstring*, _s) + 1) #define lstr(_s) cast(char*, cast(blstring*, _s) + 1) -#define cstr(_s) (cast(bcstring*, s)->s) +#define cstr(_s) (cast(bcstring*, _s)->s) #define be_define_const_str(_name, _s, _hash, _extra, _len, _next) \ BERRY_LOCAL const bcstring be_const_str_##_name = { \ @@ -45,12 +45,25 @@ int be_eqstr(bstring *s1, bstring *s2) return 1; } slen = s1->slen; + /* discard different lengths */ + if (slen != s2->slen) { + return 0; + } /* long string */ - if (slen == 255 && slen == s2->slen) { + if (slen == 255) { /* s2->slen is also 255 */ blstring *ls1 = cast(blstring*, s1); blstring *ls2 = cast(blstring*, s2); return ls1->llen == ls2->llen && !strcmp(lstr(ls1), lstr(ls2)); } + // TODO one is long const and the other is long string + /* const short strings */ + if (gc_isconst(s1) || gc_isconst(s2)) { /* one of the two string is short const */ + if (cast(bcstring*, s1)->hash && cast(bcstring*, s2)->hash) { + return 0; /* if they both have a hash, then we know they are different */ + } + return !strcmp(str(s1), str(s2)); + } + return 0; } @@ -249,7 +262,12 @@ void be_gcstrtab(bvm *vm) uint32_t be_strhash(const bstring *s) { if (gc_isconst(s)) { - return cast(bcstring*, s)->hash; + bcstring* cs = cast(bcstring*, s); + if (cs->hash) { /* if hash is null we need to compute it */ + return cs->hash; + } else { + return str_hash(cstr(s), str_len(s)); + } } #if BE_USE_STR_HASH_CACHE if (s->slen != 255) { diff --git a/lib/libesp32/Berry-0.1.10/src/be_strlib.c b/lib/libesp32/Berry-0.1.10/src/be_strlib.c index 499383774..67cb528c3 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_strlib.c +++ b/lib/libesp32/Berry-0.1.10/src/be_strlib.c @@ -336,6 +336,18 @@ bstring* be_strindex(bvm *vm, bstring *str, bvalue *idx) return NULL; } +size_t be_strlcpy(char *dst, const char *src, size_t maxlen) +{ + const size_t srclen = strlen(src); + if (srclen + 1 < maxlen) { + memcpy(dst, src, srclen + 1); + } else if (maxlen != 0) { + memcpy(dst, src, maxlen - 1); + dst[maxlen-1] = '\0'; + } + return srclen; +} + const char* be_splitpath(const char *path) { const char *p; diff --git a/lib/libesp32/Berry-0.1.10/src/be_strlib.h b/lib/libesp32/Berry-0.1.10/src/be_strlib.h index 6d0e8ebb6..992257648 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_strlib.h +++ b/lib/libesp32/Berry-0.1.10/src/be_strlib.h @@ -19,6 +19,7 @@ bstring* be_strcat(bvm *vm, bstring *s1, bstring *s2); int be_strcmp(bstring *s1, bstring *s2); bstring* be_num2str(bvm *vm, bvalue *v); void be_val2str(bvm *vm, int index); +size_t be_strlcpy(char *dst, const char *src, size_t size); const char* be_splitpath(const char *path); const char* be_splitname(const char *path); const char* be_pushvfstr(bvm *vm, const char *format, va_list arg); diff --git a/lib/libesp32/Berry-0.1.10/src/be_vm.c b/lib/libesp32/Berry-0.1.10/src/be_vm.c index ec786aa09..002dbf923 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_vm.c +++ b/lib/libesp32/Berry-0.1.10/src/be_vm.c @@ -21,6 +21,7 @@ #include "be_debug.h" #include "be_libs.h" #include +#include #define NOT_METHOD BE_NONE @@ -51,8 +52,14 @@ DEBUG_HOOK(); \ switch (IGET_OP(ins = *vm->ip++)) -#define opcase(opcode) case OP_##opcode -#define dispatch() goto loop +#if BE_USE_SINGLE_FLOAT + #define mathfunc(func) func##f +#else + #define mathfunc(func) func +#endif + +#define opcase(opcode) case OP_##opcode +#define dispatch() goto loop #define equal_rule(op, iseq) \ bbool res; \ @@ -561,6 +568,8 @@ newframe: /* a new call frame */ bvalue *dst = RA(), *a = RKB(), *b = RKC(); if (var_isint(a) && var_isint(b)) { var_setint(dst, ibinop(%, a, b)); + } else if (var_isnumber(a) && var_isnumber(b)) { + var_setreal(dst, mathfunc(fmod)(var_toreal(a), var_toreal(b))); } else if (var_isinstance(a)) { ins_binop(vm, "%", ins); } else { @@ -1055,8 +1064,11 @@ void be_dofunc(bvm *vm, bvalue *v, int argc) } } -BERRY_API void be_set_obs_hook(bvm *vm, beobshook hook) +BERRY_API void be_set_obs_hook(bvm *vm, bobshook hook) { + (void)vm; /* avoid comiler warning */ + (void)hook; /* avoid comiler warning */ + #if BE_USE_OBSERVABILITY_HOOK vm->obshook = hook; #endif diff --git a/lib/libesp32/Berry-0.1.10/src/be_vm.h b/lib/libesp32/Berry-0.1.10/src/be_vm.h index 562587100..e2df0b475 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_vm.h +++ b/lib/libesp32/Berry-0.1.10/src/be_vm.h @@ -87,7 +87,7 @@ struct bvm { blist *registry; /* registry list */ struct bgc gc; #if BE_USE_OBSERVABILITY_HOOK - beobshook obshook; + bobshook obshook; #endif #if BE_USE_DEBUG_HOOK bvalue hook; diff --git a/lib/libesp32/Berry-0.1.10/src/berry.h b/lib/libesp32/Berry-0.1.10/src/berry.h index 6bcdbc556..25e9f3c85 100644 --- a/lib/libesp32/Berry-0.1.10/src/berry.h +++ b/lib/libesp32/Berry-0.1.10/src/berry.h @@ -101,7 +101,7 @@ enum berrorcode { #elif defined(__GNUC__) /* in GCC */ #define BERRY_LOCAL __attribute__ ((visibility ("hidden"))) #else /* other platforms */ - #define BERRY_LOCAL + #define BERRY_LOCAL static #endif #ifdef __cplusplus @@ -249,6 +249,22 @@ typedef struct bntvmodule { } #endif +/* support for solidified berry functions */ +/* native const strings outside of global string hash */ +#define be_define_local_const_str(_name, _s, _hash, _extra, _len, _next) \ + BERRY_LOCAL const bcstring be_local_const_str_##_name = { \ + .next = (bgcobject *)NULL, \ + .type = BE_STRING, \ + .marked = GC_CONST, \ + .extra = 0, \ + .slen = _len, \ + .hash = 0, \ + .s = _s \ + } + +#define be_local_const_str(_name) (bstring*) &be_local_const_str_##_name + + /* debug hook typedefs */ #define BE_HOOK_LINE 1 #define BE_HOOK_CALL 2 @@ -275,7 +291,7 @@ typedef void(*bntvhook)(bvm *vm, bhookinfo *info); /* Observability hook */ -typedef void(*beobshook)(bvm *vm, int event, ...); +typedef void(*bobshook)(bvm *vm, int event, ...); enum beobshookevents { BE_OBS_GC_START, // start of GC, arg = allocated size BE_OBS_GC_END, // end of GC, arg = allocated size @@ -346,6 +362,7 @@ BERRY_API void be_pushnstring(bvm *vm, const char *str, size_t n); BERRY_API const char* be_pushfstring(bvm *vm, const char *format, ...); BERRY_API void* be_pushbuffer(bvm *vm, size_t size); BERRY_API void be_pushvalue(bvm *vm, int index); +BERRY_API void be_pushclosure(bvm *vm, void *cl); BERRY_API void be_pushntvclosure(bvm *vm, bntvfunc f, int nupvals); BERRY_API void be_pushntvfunction(bvm *vm, bntvfunc f); BERRY_API void be_pushclass(bvm *vm, const char *name, const bnfuncinfo *lib); @@ -416,7 +433,7 @@ BERRY_API bvm* be_vm_new(void); BERRY_API void be_vm_delete(bvm *vm); /* Observability hook */ -BERRY_API void be_set_obs_hook(bvm *vm, beobshook hook); +BERRY_API void be_set_obs_hook(bvm *vm, bobshook hook); /* code load APIs */ BERRY_API int be_loadbuffer(bvm *vm, @@ -431,7 +448,7 @@ BERRY_API void be_module_path_set(bvm *vm, const char *path); /* bytes operations */ BERRY_API void be_pushbytes(bvm *vm, const void *buf, size_t len); -BERRY_API const void *be_tobytes(bvm *vm, int index, size_t *len); +BERRY_API const void* be_tobytes(bvm *vm, int index, size_t *len); /* registry operation */ BERRY_API int be_register(bvm *vm, int index); diff --git a/lib/libesp32/Berry-0.1.10/src/port/be_driverlib.c b/lib/libesp32/Berry-0.1.10/src/port/be_driverlib.c new file mode 100644 index 000000000..4e9b8cce8 --- /dev/null +++ b/lib/libesp32/Berry-0.1.10/src/port/be_driverlib.c @@ -0,0 +1,34 @@ +/******************************************************************** + * Tasmota lib + * + * To use: `d = Driver()` + * + *******************************************************************/ +#include "be_object.h" + +// #if !BE_USE_PRECOMPILED_OBJECT +#if 1 // TODO we will do pre-compiled later +void be_load_driverlib(bvm *vm) +{ + static const bnfuncinfo members[] = { + { "every_second", NULL }, + { "every_100ms", NULL }, + { "web_add_button", NULL }, + { "web_add_main_button", NULL }, + { "save_before_restart", NULL }, + { "web_sensor", NULL }, + { "json_append", NULL }, + { "button_pressed", NULL }, + + { NULL, NULL } + }; + be_regclass(vm, "Driver", members); +} +#else +/* @const_object_info_begin +module tasmota (scope: global, depend: 1) { + get_free_heap, func(l_getFreeHeap) +} +@const_object_info_end */ +#include "../generate/be_fixed_tasmota.h" +#endif diff --git a/lib/libesp32/Berry-0.1.10/src/port/be_modtab.c b/lib/libesp32/Berry-0.1.10/src/port/be_modtab.c index fa3f09479..e0a82d149 100644 --- a/lib/libesp32/Berry-0.1.10/src/port/be_modtab.c +++ b/lib/libesp32/Berry-0.1.10/src/port/be_modtab.c @@ -18,6 +18,7 @@ be_extern_native_module(os); be_extern_native_module(sys); be_extern_native_module(debug); be_extern_native_module(gc); +be_extern_native_module(solidify); /* Tasmota specific */ // be_extern_native_module(tasmota_ntv); @@ -54,6 +55,9 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { #endif #if BE_USE_GC_MODULE &be_native_module(gc), +#endif +#if BE_USE_SOLIDIFY_MODULE + &be_native_module(solidify), #endif /* user-defined modules register start */ @@ -62,3 +66,21 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { /* user-defined modules register end */ NULL /* do not remove */ }; + +extern void be_load_tasmota_ntvlib(bvm *vm); +extern void be_load_wirelib(bvm *vm); +extern void be_load_driverlib(bvm *vm); + +/* this code loads the native class definitions */ +BERRY_API void be_load_custom_libs(bvm *vm) +{ + (void)vm; /* prevent a compiler warning */ + + /* add here custom libs */ +#if !BE_USE_PRECOMPILED_OBJECT + /* be_load_xxxlib(vm); */ +#endif + be_load_tasmota_ntvlib(vm); + be_load_wirelib(vm); + be_load_driverlib(vm); +} diff --git a/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c b/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c index 713effefd..95eab5c34 100644 --- a/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c +++ b/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c @@ -4,6 +4,8 @@ * To use: `import tasmota` *******************************************************************/ #include "be_object.h" +#include "be_string.h" +#include "be_gc.h" extern int l_getFreeHeap(bvm *vm); extern int l_publish(bvm *vm); @@ -14,6 +16,8 @@ extern int l_timereached(bvm *vm); extern int l_yield(bvm *vm); extern int l_delay(bvm *vm); extern int l_scaleuint(bvm *vm); +extern int l_logInfo(bvm *vm); +extern int l_save(bvm *vm); extern int l_respCmnd(bvm *vm); extern int l_respCmndStr(bvm *vm); @@ -22,6 +26,9 @@ extern int l_respCmndError(bvm *vm); extern int l_respCmndFailed(bvm *vm); extern int l_resolveCmnd(bvm *vm); +extern int l_respAppend(bvm *vm); +extern int l_webSendDecimal(bvm *vm); + extern int l_getlight(bvm *vm); extern int l_getpower(bvm *vm); extern int l_setlight(bvm *vm); @@ -29,15 +36,1824 @@ extern int l_setpower(bvm *vm); extern int l_i2cenabled(bvm *vm); + +/******************************************************************** + // add `chars_in_string(s:string,c:string) -> int`` + // looks for any char in c, and return the position of the first char + // or -1 if not found + // inv is optional and inverses the behavior, i.e. look for chars not in the list + "def chars_in_string(s,c,inv) " + "var inverted = inv ? true : false " + "for i:0..size(s)-1 " + "var found = false " + "for j:0..size(c)-1 " + "if s[i] == c[j] found = true end " + "end " + "if inverted != found return i end " + "end " + "return -1 " + "end " +********************************************************************/ +/******************************************************************** +** Solidified function: chars_in_string +********************************************************************/ + +be_define_local_const_str(chars_in_string_str_name, "chars_in_string", -1146182164, 0, 15, 0); +be_define_local_const_str(chars_in_string_str_source, "string", 398550328, 0, 6, 0); +be_define_local_const_str(chars_in_string_str_2, "stop_iteration", -121173395, 0, 14, 0); + +static const bvalue chars_in_string_ktab[3] = { + { { .i=0 }, BE_INT}, + { { .i=1 }, BE_INT}, + { { .s=be_local_const_str(chars_in_string_str_2) }, BE_STRING}, +}; + +static const uint32_t chars_in_string_code[44] = { + 0x780E0001, // 0000 JMPF R3 #0003 + 0x50100200, // 0001 LDBOOL R4 1 0 + 0x70020000, // 0002 JMP #0004 + 0x50100000, // 0003 LDBOOL R4 0 0 + 0x60140000, // 0004 GETGBL R5 G0 + 0x60180012, // 0005 GETGBL R6 G18 + 0x5C1C0200, // 0006 MOVE R7 R1 + 0x7C180200, // 0007 CALL R6 1 + 0x4180D01, // 0008 SUB R6 R6 R257 + 0x401A0006, // 0009 CONNECT R6 R256 R6 + 0x7C140200, // 000A CALL R5 1 + 0xA802001A, // 000B EXBLK 0 #0027 + 0x5C180A00, // 000C MOVE R6 R5 + 0x7C180000, // 000D CALL R6 0 + 0x501C0000, // 000E LDBOOL R7 0 0 + 0x60200000, // 000F GETGBL R8 G0 + 0x60240012, // 0010 GETGBL R9 G18 + 0x5C280400, // 0011 MOVE R10 R2 + 0x7C240200, // 0012 CALL R9 1 + 0x4241301, // 0013 SUB R9 R9 R257 + 0x40260009, // 0014 CONNECT R9 R256 R9 + 0x7C200200, // 0015 CALL R8 1 + 0xA8020007, // 0016 EXBLK 0 #001F + 0x5C241000, // 0017 MOVE R9 R8 + 0x7C240000, // 0018 CALL R9 0 + 0x94280206, // 0019 GETIDX R10 R1 R6 + 0x942C0409, // 001A GETIDX R11 R2 R9 + 0x1C28140B, // 001B EQ R10 R10 R11 + 0x782A0000, // 001C JMPF R10 #001E + 0x501C0200, // 001D LDBOOL R7 1 0 + 0x7001FFF7, // 001E JMP #0017 + 0x58200002, // 001F LDCONST R8 K2 + 0xAC200200, // 0020 CATCH R8 1 0 + 0xB0080000, // 0021 RAISE 2 R0 R0 + 0x20200807, // 0022 NE R8 R4 R7 + 0x78220001, // 0023 JMPF R8 #0026 + 0xA8040001, // 0024 EXBLK 1 1 + 0x80040C00, // 0025 RET 1 R6 + 0x7001FFE4, // 0026 JMP #000C + 0x58140002, // 0027 LDCONST R5 K2 + 0xAC140200, // 0028 CATCH R5 1 0 + 0xB0080000, // 0029 RAISE 2 R0 R0 + 0x5415FFFE, // 002A LDINT R5 -1 + 0x80040A00, // 002B RET 1 R5 +}; + +static const bproto chars_in_string_proto = { + NULL, // bgcobject *next + 8, // type + GC_CONST, // marked + 12, // nstack + 0, // nupvals + 4, // argc + 0, // varg + NULL, // bgcobject *gray + NULL, // bupvaldesc *upvals + (bvalue*) &chars_in_string_ktab, // ktab + NULL, // bproto **ptab + (binstruction*) &chars_in_string_code, // code + be_local_const_str(chars_in_string_str_name), // name + 44, // codesize + 3, // nconst + 0, // nproto + be_local_const_str(chars_in_string_str_source), // source +#if BE_DEBUG_RUNTIME_INFO /* debug information */ + NULL, // lineinfo + 0, // nlineinfo +#endif +#if BE_DEBUG_VAR_INFO + NULL, // varinfo + 0, // nvarinfo +#endif +}; + +const bclosure chars_in_string_closure = { + NULL, // bgcobject *next + 36, // type + GC_CONST, // marked + 0, // nupvals + NULL, // bgcobject *gray + (bproto*) &chars_in_string_proto, // proto + { NULL } // upvals +}; + +/*******************************************************************/ + + +/******************************************************************** +// find a key in map, case insensitive, return actual key or nil if not found +def find_key_i(m,keyi) + import string + var keyu = string.toupper(keyi) + if classof(m) == map + for k:m.keys() + if string.toupper(k)==keyu || keyi=='?' + return k + end + end + end +end +********************************************************************/ +/******************************************************************** +** Solidified function: find_key_i +********************************************************************/ + +be_define_local_const_str(find_key_i_str_name, "find_key_i", 850136726, 0, 10, 0); +be_define_local_const_str(find_key_i_str_source, "string", 398550328, 0, 6, 0); +be_define_local_const_str(find_key_i_str_0, "string", 398550328, 0, 6, 0); +be_define_local_const_str(find_key_i_str_1, "toupper", -602983720, 0, 7, 0); +be_define_local_const_str(find_key_i_str_2, "keys", -112588595, 0, 4, 0); +be_define_local_const_str(find_key_i_str_3, "?", 973910158, 0, 1, 0); +be_define_local_const_str(find_key_i_str_4, "stop_iteration", -121173395, 0, 14, 0); + +static const bvalue find_key_i_ktab[5] = { + { { .s=be_local_const_str(find_key_i_str_0) }, BE_STRING}, + { { .s=be_local_const_str(find_key_i_str_1) }, BE_STRING}, + { { .s=be_local_const_str(find_key_i_str_2) }, BE_STRING}, + { { .s=be_local_const_str(find_key_i_str_3) }, BE_STRING}, + { { .s=be_local_const_str(find_key_i_str_4) }, BE_STRING}, +}; + +static const uint32_t find_key_i_code[31] = { + 0xA40E0000, // 0000 IMPORT R3 R256 + 0x8C100701, // 0001 GETMET R4 R3 R257 + 0x5C180400, // 0002 MOVE R6 R2 + 0x7C100400, // 0003 CALL R4 2 + 0x60140004, // 0004 GETGBL R5 G4 + 0x5C180200, // 0005 MOVE R6 R1 + 0x7C140200, // 0006 CALL R5 1 + 0x6018000B, // 0007 GETGBL R6 G11 + 0x1C140A06, // 0008 EQ R5 R5 R6 + 0x78160013, // 0009 JMPF R5 #001E + 0x60140000, // 000A GETGBL R5 G0 + 0x8C180302, // 000B GETMET R6 R1 R258 + 0x7C180200, // 000C CALL R6 1 + 0x7C140200, // 000D CALL R5 1 + 0xA802000B, // 000E EXBLK 0 #001B + 0x5C180A00, // 000F MOVE R6 R5 + 0x7C180000, // 0010 CALL R6 0 + 0x8C1C0701, // 0011 GETMET R7 R3 R257 + 0x5C240C00, // 0012 MOVE R9 R6 + 0x7C1C0400, // 0013 CALL R7 2 + 0x1C1C0E04, // 0014 EQ R7 R7 R4 + 0x741E0001, // 0015 JMPT R7 #0018 + 0x1C1C0503, // 0016 EQ R7 R2 R259 + 0x781E0001, // 0017 JMPF R7 #001A + 0xA8040001, // 0018 EXBLK 1 1 + 0x80040C00, // 0019 RET 1 R6 + 0x7001FFF3, // 001A JMP #000F + 0x58140004, // 001B LDCONST R5 K4 + 0xAC140200, // 001C CATCH R5 1 0 + 0xB0080000, // 001D RAISE 2 R0 R0 + 0x80000000, // 001E RET 0 R0 +}; + +static const bproto find_key_i_proto = { + NULL, // bgcobject *next + 8, // type + GC_CONST, // marked + 10, // nstack + 0, // nupvals + 3, // argc + 0, // varg + NULL, // bgcobject *gray + NULL, // bupvaldesc *upvals + (bvalue*) &find_key_i_ktab, // ktab + NULL, // bproto **ptab + (binstruction*) &find_key_i_code, // code + be_local_const_str(find_key_i_str_name), // name + 31, // codesize + 5, // nconst + 0, // nproto + be_local_const_str(find_key_i_str_source), // source +#if BE_DEBUG_RUNTIME_INFO /* debug information */ + NULL, // lineinfo + 0, // nlineinfo +#endif +#if BE_DEBUG_VAR_INFO + NULL, // varinfo + 0, // nvarinfo +#endif +}; + +const bclosure find_key_i_closure = { + NULL, // bgcobject *next + 36, // type + GC_CONST, // marked + 0, // nupvals + NULL, // bgcobject *gray + (bproto*) &find_key_i_proto, // proto + { NULL } // upvals +}; + +/*******************************************************************/ + + + +/******************************************************************** + // # split the item when there is an operator, returns a list of (left,op,right) + // # ex: "Dimmer>50" -> ["Dimmer",tasmota_gt,"50"] + "def find_op(item) " + "import string " + "var op_chars = '=<>!' " + "var pos = self.chars_in_string(item, op_chars) " + "if pos >= 0 " + "var op_split = string.split(item,pos) " + "var op_left = op_split[0] " + "var op_rest = op_split[1] " + "pos = self.chars_in_string(op_rest, op_chars, true) " + "if pos >= 0 " + "var op_split2 = string.split(op_rest,pos) " + "var op_middle = op_split2[0] " + "var op_right = op_split2[1] " + "return [op_left,op_middle,op_right] " + "end " + "end " + "return [item, nil, nil] " + "end " +********************************************************************/ +/******************************************************************** +** Solidified function: find_op +********************************************************************/ + +be_define_local_const_str(find_op_str_name, "find_op", -528253920, 0, 7, 0); +be_define_local_const_str(find_op_str_source, "string", 398550328, 0, 6, 0); +be_define_local_const_str(find_op_str_0, "string", 398550328, 0, 6, 0); +be_define_local_const_str(find_op_str_1, "=<>!", -1630497019, 0, 4, 0); +be_define_local_const_str(find_op_str_2, "chars_in_string", -1146182164, 0, 15, 0); +be_define_local_const_str(find_op_str_4, "split", -2017972765, 0, 5, 0); + +static const bvalue find_op_ktab[6] = { + { { .s=be_local_const_str(find_op_str_0) }, BE_STRING}, + { { .s=be_local_const_str(find_op_str_1) }, BE_STRING}, + { { .s=be_local_const_str(find_op_str_2) }, BE_STRING}, + { { .i=0 }, BE_INT}, + { { .s=be_local_const_str(find_op_str_4) }, BE_STRING}, + { { .i=1 }, BE_INT}, +}; + +static const uint32_t find_op_code[42] = { + 0xA40A0000, // 0000 IMPORT R2 R256 + 0x580C0001, // 0001 LDCONST R3 K1 + 0x8C100102, // 0002 GETMET R4 R0 R258 + 0x5C180200, // 0003 MOVE R6 R1 + 0x5C1C0600, // 0004 MOVE R7 R3 + 0x7C100600, // 0005 CALL R4 3 + 0x28140903, // 0006 GE R5 R4 R259 + 0x78160019, // 0007 JMPF R5 #0022 + 0x8C140504, // 0008 GETMET R5 R2 R260 + 0x5C1C0200, // 0009 MOVE R7 R1 + 0x5C200800, // 000A MOVE R8 R4 + 0x7C140600, // 000B CALL R5 3 + 0x94180B03, // 000C GETIDX R6 R5 R259 + 0x941C0B05, // 000D GETIDX R7 R5 R261 + 0x8C200102, // 000E GETMET R8 R0 R258 + 0x5C280E00, // 000F MOVE R10 R7 + 0x5C2C0600, // 0010 MOVE R11 R3 + 0x50300200, // 0011 LDBOOL R12 1 0 + 0x7C200800, // 0012 CALL R8 4 + 0x5C101000, // 0013 MOVE R4 R8 + 0x28200903, // 0014 GE R8 R4 R259 + 0x7822000B, // 0015 JMPF R8 #0022 + 0x8C200504, // 0016 GETMET R8 R2 R260 + 0x5C280E00, // 0017 MOVE R10 R7 + 0x5C2C0800, // 0018 MOVE R11 R4 + 0x7C200600, // 0019 CALL R8 3 + 0x94241103, // 001A GETIDX R9 R8 R259 + 0x94281105, // 001B GETIDX R10 R8 R261 + 0x602C000A, // 001C GETGBL R11 G10 + 0x7C2C0000, // 001D CALL R11 0 + 0x40301606, // 001E CONNECT R12 R11 R6 + 0x40301609, // 001F CONNECT R12 R11 R9 + 0x4030160A, // 0020 CONNECT R12 R11 R10 + 0x80041600, // 0021 RET 1 R11 + 0x6014000A, // 0022 GETGBL R5 G10 + 0x7C140000, // 0023 CALL R5 0 + 0x40180A01, // 0024 CONNECT R6 R5 R1 + 0x4C180000, // 0025 LDNIL 6 + 0x40180A06, // 0026 CONNECT R6 R5 R6 + 0x4C180000, // 0027 LDNIL 6 + 0x40180A06, // 0028 CONNECT R6 R5 R6 + 0x80040A00, // 0029 RET 1 R5 +}; + +static const bproto find_op_proto = { + NULL, // bgcobject *next + 8, // type + GC_CONST, // marked + 13, // nstack + 0, // nupvals + 2, // argc + 0, // varg + NULL, // bgcobject *gray + NULL, // bupvaldesc *upvals + (bvalue*) &find_op_ktab, // ktab + NULL, // bproto **ptab + (binstruction*) &find_op_code, // code + be_local_const_str(find_op_str_name), // name + 42, // codesize + 6, // nconst + 0, // nproto + be_local_const_str(find_op_str_source), // source +#if BE_DEBUG_RUNTIME_INFO /* debug information */ + NULL, // lineinfo + 0, // nlineinfo +#endif +#if BE_DEBUG_VAR_INFO + NULL, // varinfo + 0, // nvarinfo +#endif +}; + +const bclosure find_op_closure = { + NULL, // bgcobject *next + 36, // type + GC_CONST, // marked + 0, // nupvals + NULL, // bgcobject *gray + (bproto*) &find_op_proto, // proto + { NULL } // upvals +}; + +/*******************************************************************/ + + +/******************************************************************** + // Rules + "def add_rule(pat,f) " + "if !self._rules " + "self._rules={} " + "end " + "self._rules[pat] = f " + "end " +********************************************************************/ + +/******************************************************************** +** Solidified function: add_rule +********************************************************************/ + +be_define_local_const_str(add_rule_str_name, "add_rule", 596540743, 0, 8, 0); +be_define_local_const_str(add_rule_str_source, "string", 398550328, 0, 6, 0); +be_define_local_const_str(add_rule_str_0, "_rules", -28750191, 0, 6, 0); + +static const bvalue add_rule_ktab[1] = { + { { .s=be_local_const_str(add_rule_str_0) }, BE_STRING}, +}; + +static const uint32_t add_rule_code[8] = { + 0x880C0100, // 0000 GETMBR R3 R0 R256 + 0x740E0002, // 0001 JMPT R3 #0005 + 0x600C000B, // 0002 GETGBL R3 G11 + 0x7C0C0000, // 0003 CALL R3 0 + 0x90020003, // 0004 SETMBR R0 R256 R3 + 0x880C0100, // 0005 GETMBR R3 R0 R256 + 0x980C0202, // 0006 SETIDX R3 R1 R2 + 0x80000000, // 0007 RET 0 R0 +}; + +static const bproto add_rule_proto = { + NULL, // bgcobject *next + 8, // type + GC_CONST, // marked + 4, // nstack + 0, // nupvals + 3, // argc + 0, // varg + NULL, // bgcobject *gray + NULL, // bupvaldesc *upvals + (bvalue*) &add_rule_ktab, // ktab + NULL, // bproto **ptab + (binstruction*) &add_rule_code, // code + be_local_const_str(add_rule_str_name), // name + 8, // codesize + 1, // nconst + 0, // nproto + be_local_const_str(add_rule_str_source), // source +#if BE_DEBUG_RUNTIME_INFO /* debug information */ + NULL, // lineinfo + 0, // nlineinfo +#endif +#if BE_DEBUG_VAR_INFO + NULL, // varinfo + 0, // nvarinfo +#endif +}; + +const bclosure add_rule_closure = { + NULL, // bgcobject *next + 36, // type + GC_CONST, // marked + 0, // nupvals + NULL, // bgcobject *gray + (bproto*) &add_rule_proto, // proto + { NULL } // upvals +}; + +/*******************************************************************/ + + + +/******************************************************************** + // Rules trigger if match. return true if match, false if not + "def try_rule(ev, rule, f) " + "import string " + "var rl_list = self.find_op(rule) " + "var e=ev " + "var rl=string.split(rl_list[0],'#') " + "for it:rl " + "found=self.find_key_i(e,it) " + "if found == nil return false end " + "e=e[found] " + "end " + "var op=rl_list[1]" + "var op2=rl_list[2]" + "if op " + "if op=='==' " + "if str(e) != str(op2) return false end " + "elif op=='!==' " + "if str(e) == str(op2) return false end " + "elif op=='=' " + "if real(e) != real(op2) return false end " + "elif op=='!=' " + "if real(e) == real(op2) return false end " + "elif op=='>' " + "if real(e) <= real(op2) return false end " + "elif op=='>=' " + "if real(e) < real(op2) return false end " + "elif op=='<' " + "if real(e) >= real(op2) return false end " + "elif op=='<=' " + "if real(e) > real(op2) return false end " + "end " + "end " + "f(e,ev) " + "return true " + "end " +********************************************************************/ + +/******************************************************************** +** Solidified function: try_rule +********************************************************************/ + +be_define_local_const_str(try_rule_str_name, "try_rule", 1986449405, 0, 8, 0); +be_define_local_const_str(try_rule_str_source, "string", 398550328, 0, 6, 0); +be_define_local_const_str(try_rule_str_0, "string", 398550328, 0, 6, 0); +be_define_local_const_str(try_rule_str_1, "find_op", -528253920, 0, 7, 0); +be_define_local_const_str(try_rule_str_2, "split", -2017972765, 0, 5, 0); +be_define_local_const_str(try_rule_str_4, "#", 638357778, 0, 1, 0); +be_define_local_const_str(try_rule_str_5, "find_key_i", 850136726, 0, 10, 0); +be_define_local_const_str(try_rule_str_6, "stop_iteration", -121173395, 0, 14, 0); +be_define_local_const_str(try_rule_str_9, "==", -1863000881, 0, 2, 0); +be_define_local_const_str(try_rule_str_10, "!==", 559817114, 0, 3, 0); +be_define_local_const_str(try_rule_str_11, "=", 940354920, 0, 1, 0); +be_define_local_const_str(try_rule_str_12, "!=", -1866252285, 0, 2, 0); +be_define_local_const_str(try_rule_str_13, ">", 990687777, 0, 1, 0); +be_define_local_const_str(try_rule_str_14, ">=", 284975636, 0, 2, 0); +be_define_local_const_str(try_rule_str_15, "<", 957132539, 0, 1, 0); +be_define_local_const_str(try_rule_str_16, "<=", -1795743310, 0, 2, 0); + +static const bvalue try_rule_ktab[17] = { + { { .s=be_local_const_str(try_rule_str_0) }, BE_STRING}, + { { .s=be_local_const_str(try_rule_str_1) }, BE_STRING}, + { { .s=be_local_const_str(try_rule_str_2) }, BE_STRING}, + { { .i=0 }, BE_INT}, + { { .s=be_local_const_str(try_rule_str_4) }, BE_STRING}, + { { .s=be_local_const_str(try_rule_str_5) }, BE_STRING}, + { { .s=be_local_const_str(try_rule_str_6) }, BE_STRING}, + { { .i=1 }, BE_INT}, + { { .i=2 }, BE_INT}, + { { .s=be_local_const_str(try_rule_str_9) }, BE_STRING}, + { { .s=be_local_const_str(try_rule_str_10) }, BE_STRING}, + { { .s=be_local_const_str(try_rule_str_11) }, BE_STRING}, + { { .s=be_local_const_str(try_rule_str_12) }, BE_STRING}, + { { .s=be_local_const_str(try_rule_str_13) }, BE_STRING}, + { { .s=be_local_const_str(try_rule_str_14) }, BE_STRING}, + { { .s=be_local_const_str(try_rule_str_15) }, BE_STRING}, + { { .s=be_local_const_str(try_rule_str_16) }, BE_STRING}, +}; + +static const uint32_t try_rule_code[142] = { + 0xA4120000, // 0000 IMPORT R4 R256 + 0x8C140101, // 0001 GETMET R5 R0 R257 + 0x5C1C0400, // 0002 MOVE R7 R2 + 0x7C140400, // 0003 CALL R5 2 + 0x5C180200, // 0004 MOVE R6 R1 + 0x8C1C0902, // 0005 GETMET R7 R4 R258 + 0x94240B03, // 0006 GETIDX R9 R5 R259 + 0x58280004, // 0007 LDCONST R10 K4 + 0x7C1C0600, // 0008 CALL R7 3 + 0x60200000, // 0009 GETGBL R8 G0 + 0x5C240E00, // 000A MOVE R9 R7 + 0x7C200200, // 000B CALL R8 1 + 0xA802000D, // 000C EXBLK 0 #001B + 0x5C241000, // 000D MOVE R9 R8 + 0x7C240000, // 000E CALL R9 0 + 0x8C280105, // 000F GETMET R10 R0 R261 + 0x5C300C00, // 0010 MOVE R12 R6 + 0x5C341200, // 0011 MOVE R13 R9 + 0x7C280600, // 0012 CALL R10 3 + 0x4C2C0000, // 0013 LDNIL 11 + 0x1C2C140B, // 0014 EQ R11 R10 R11 + 0x782E0002, // 0015 JMPF R11 #0019 + 0x502C0000, // 0016 LDBOOL R11 0 0 + 0xA8040001, // 0017 EXBLK 1 1 + 0x80041600, // 0018 RET 1 R11 + 0x94180C0A, // 0019 GETIDX R6 R6 R10 + 0x7001FFF1, // 001A JMP #000D + 0x58200006, // 001B LDCONST R8 K6 + 0xAC200200, // 001C CATCH R8 1 0 + 0xB0080000, // 001D RAISE 2 R0 R0 + 0x94200B07, // 001E GETIDX R8 R5 R263 + 0x94240B08, // 001F GETIDX R9 R5 R264 + 0x78220066, // 0020 JMPF R8 #0088 + 0x1C281109, // 0021 EQ R10 R8 R265 + 0x782A000A, // 0022 JMPF R10 #002E + 0x60280013, // 0023 GETGBL R10 G19 + 0x5C2C0C00, // 0024 MOVE R11 R6 + 0x7C280200, // 0025 CALL R10 1 + 0x602C0013, // 0026 GETGBL R11 G19 + 0x5C301200, // 0027 MOVE R12 R9 + 0x7C2C0200, // 0028 CALL R11 1 + 0x2028140B, // 0029 NE R10 R10 R11 + 0x782A0001, // 002A JMPF R10 #002D + 0x50280000, // 002B LDBOOL R10 0 0 + 0x80041400, // 002C RET 1 R10 + 0x70020059, // 002D JMP #0088 + 0x1C28110A, // 002E EQ R10 R8 R266 + 0x782A000A, // 002F JMPF R10 #003B + 0x60280013, // 0030 GETGBL R10 G19 + 0x5C2C0C00, // 0031 MOVE R11 R6 + 0x7C280200, // 0032 CALL R10 1 + 0x602C0013, // 0033 GETGBL R11 G19 + 0x5C301200, // 0034 MOVE R12 R9 + 0x7C2C0200, // 0035 CALL R11 1 + 0x1C28140B, // 0036 EQ R10 R10 R11 + 0x782A0001, // 0037 JMPF R10 #003A + 0x50280000, // 0038 LDBOOL R10 0 0 + 0x80041400, // 0039 RET 1 R10 + 0x7002004C, // 003A JMP #0088 + 0x1C28110B, // 003B EQ R10 R8 R267 + 0x782A000A, // 003C JMPF R10 #0048 + 0x60280011, // 003D GETGBL R10 G17 + 0x5C2C0C00, // 003E MOVE R11 R6 + 0x7C280200, // 003F CALL R10 1 + 0x602C0011, // 0040 GETGBL R11 G17 + 0x5C301200, // 0041 MOVE R12 R9 + 0x7C2C0200, // 0042 CALL R11 1 + 0x2028140B, // 0043 NE R10 R10 R11 + 0x782A0001, // 0044 JMPF R10 #0047 + 0x50280000, // 0045 LDBOOL R10 0 0 + 0x80041400, // 0046 RET 1 R10 + 0x7002003F, // 0047 JMP #0088 + 0x1C28110C, // 0048 EQ R10 R8 R268 + 0x782A000A, // 0049 JMPF R10 #0055 + 0x60280011, // 004A GETGBL R10 G17 + 0x5C2C0C00, // 004B MOVE R11 R6 + 0x7C280200, // 004C CALL R10 1 + 0x602C0011, // 004D GETGBL R11 G17 + 0x5C301200, // 004E MOVE R12 R9 + 0x7C2C0200, // 004F CALL R11 1 + 0x1C28140B, // 0050 EQ R10 R10 R11 + 0x782A0001, // 0051 JMPF R10 #0054 + 0x50280000, // 0052 LDBOOL R10 0 0 + 0x80041400, // 0053 RET 1 R10 + 0x70020032, // 0054 JMP #0088 + 0x1C28110D, // 0055 EQ R10 R8 R269 + 0x782A000A, // 0056 JMPF R10 #0062 + 0x60280011, // 0057 GETGBL R10 G17 + 0x5C2C0C00, // 0058 MOVE R11 R6 + 0x7C280200, // 0059 CALL R10 1 + 0x602C0011, // 005A GETGBL R11 G17 + 0x5C301200, // 005B MOVE R12 R9 + 0x7C2C0200, // 005C CALL R11 1 + 0x1828140B, // 005D LE R10 R10 R11 + 0x782A0001, // 005E JMPF R10 #0061 + 0x50280000, // 005F LDBOOL R10 0 0 + 0x80041400, // 0060 RET 1 R10 + 0x70020025, // 0061 JMP #0088 + 0x1C28110E, // 0062 EQ R10 R8 R270 + 0x782A000A, // 0063 JMPF R10 #006F + 0x60280011, // 0064 GETGBL R10 G17 + 0x5C2C0C00, // 0065 MOVE R11 R6 + 0x7C280200, // 0066 CALL R10 1 + 0x602C0011, // 0067 GETGBL R11 G17 + 0x5C301200, // 0068 MOVE R12 R9 + 0x7C2C0200, // 0069 CALL R11 1 + 0x1428140B, // 006A LT R10 R10 R11 + 0x782A0001, // 006B JMPF R10 #006E + 0x50280000, // 006C LDBOOL R10 0 0 + 0x80041400, // 006D RET 1 R10 + 0x70020018, // 006E JMP #0088 + 0x1C28110F, // 006F EQ R10 R8 R271 + 0x782A000A, // 0070 JMPF R10 #007C + 0x60280011, // 0071 GETGBL R10 G17 + 0x5C2C0C00, // 0072 MOVE R11 R6 + 0x7C280200, // 0073 CALL R10 1 + 0x602C0011, // 0074 GETGBL R11 G17 + 0x5C301200, // 0075 MOVE R12 R9 + 0x7C2C0200, // 0076 CALL R11 1 + 0x2828140B, // 0077 GE R10 R10 R11 + 0x782A0001, // 0078 JMPF R10 #007B + 0x50280000, // 0079 LDBOOL R10 0 0 + 0x80041400, // 007A RET 1 R10 + 0x7002000B, // 007B JMP #0088 + 0x1C281110, // 007C EQ R10 R8 R272 + 0x782A0009, // 007D JMPF R10 #0088 + 0x60280011, // 007E GETGBL R10 G17 + 0x5C2C0C00, // 007F MOVE R11 R6 + 0x7C280200, // 0080 CALL R10 1 + 0x602C0011, // 0081 GETGBL R11 G17 + 0x5C301200, // 0082 MOVE R12 R9 + 0x7C2C0200, // 0083 CALL R11 1 + 0x2428140B, // 0084 GT R10 R10 R11 + 0x782A0001, // 0085 JMPF R10 #0088 + 0x50280000, // 0086 LDBOOL R10 0 0 + 0x80041400, // 0087 RET 1 R10 + 0x5C280600, // 0088 MOVE R10 R3 + 0x5C2C0C00, // 0089 MOVE R11 R6 + 0x5C300200, // 008A MOVE R12 R1 + 0x7C280400, // 008B CALL R10 2 + 0x50280200, // 008C LDBOOL R10 1 0 + 0x80041400, // 008D RET 1 R10 +}; + +static const bproto try_rule_proto = { + NULL, // bgcobject *next + 8, // type + GC_CONST, // marked + 14, // nstack + 0, // nupvals + 4, // argc + 0, // varg + NULL, // bgcobject *gray + NULL, // bupvaldesc *upvals + (bvalue*) &try_rule_ktab, // ktab + NULL, // bproto **ptab + (binstruction*) &try_rule_code, // code + be_local_const_str(try_rule_str_name), // name + 142, // codesize + 17, // nconst + 0, // nproto + be_local_const_str(try_rule_str_source), // source +#if BE_DEBUG_RUNTIME_INFO /* debug information */ + NULL, // lineinfo + 0, // nlineinfo +#endif +#if BE_DEBUG_VAR_INFO + NULL, // varinfo + 0, // nvarinfo +#endif +}; + +const bclosure try_rule_closure = { + NULL, // bgcobject *next + 36, // type + GC_CONST, // marked + 0, // nupvals + NULL, // bgcobject *gray + (bproto*) &try_rule_proto, // proto + { NULL } // upvals +}; + +/*******************************************************************/ + + +/******************************************************************** + // Run rules, i.e. check each individual rule + // Returns true if at least one rule matched, false if none + "def exec_rules(ev_json) " + "if self._rules " + "import json " + "var ev = json.load(ev_json) " + "var ret = false " + "if ev == nil " + "print('BRY: ERROR, bad json: '+ev_json, 3) " + "else " + "for r: self._rules.keys() " + "ret = self.try_rule(ev,r,self._rules[r]) || ret " + "end " + "end " + "return ret " + "end " + "return false " + "end " + +********************************************************************/ + +/******************************************************************** +** Solidified function: exec_rules +********************************************************************/ + +be_define_local_const_str(exec_rules_str_name, "exec_rules", 1445221092, 0, 10, 0); +be_define_local_const_str(exec_rules_str_source, "string", 398550328, 0, 6, 0); +be_define_local_const_str(exec_rules_str_0, "_rules", -28750191, 0, 6, 0); +be_define_local_const_str(exec_rules_str_1, "json", 916562499, 0, 4, 0); +be_define_local_const_str(exec_rules_str_2, "load", -435725847, 0, 4, 0); +be_define_local_const_str(exec_rules_str_3, "BRY: ERROR, bad json: ", -1579831487, 0, 22, 0); +be_define_local_const_str(exec_rules_str_5, "keys", -112588595, 0, 4, 0); +be_define_local_const_str(exec_rules_str_6, "try_rule", 1986449405, 0, 8, 0); +be_define_local_const_str(exec_rules_str_7, "stop_iteration", -121173395, 0, 14, 0); + +static const bvalue exec_rules_ktab[8] = { + { { .s=be_local_const_str(exec_rules_str_0) }, BE_STRING}, + { { .s=be_local_const_str(exec_rules_str_1) }, BE_STRING}, + { { .s=be_local_const_str(exec_rules_str_2) }, BE_STRING}, + { { .s=be_local_const_str(exec_rules_str_3) }, BE_STRING}, + { { .i=3 }, BE_INT}, + { { .s=be_local_const_str(exec_rules_str_5) }, BE_STRING}, + { { .s=be_local_const_str(exec_rules_str_6) }, BE_STRING}, + { { .s=be_local_const_str(exec_rules_str_7) }, BE_STRING}, +}; + +static const uint32_t exec_rules_code[40] = { + 0x88080100, // 0000 GETMBR R2 R0 R256 + 0x780A0023, // 0001 JMPF R2 #0026 + 0xA40A0200, // 0002 IMPORT R2 R257 + 0x8C0C0502, // 0003 GETMET R3 R2 R258 + 0x5C140200, // 0004 MOVE R5 R1 + 0x7C0C0400, // 0005 CALL R3 2 + 0x50100000, // 0006 LDBOOL R4 0 0 + 0x4C140000, // 0007 LDNIL 5 + 0x1C140605, // 0008 EQ R5 R3 R5 + 0x78160004, // 0009 JMPF R5 #000F + 0x6014000F, // 000A GETGBL R5 G15 + 0x1A0601, // 000B ADD R6 R259 R1 + 0x581C0004, // 000C LDCONST R7 K4 + 0x7C140400, // 000D CALL R5 2 + 0x70020015, // 000E JMP #0025 + 0x60140000, // 000F GETGBL R5 G0 + 0x88180100, // 0010 GETMBR R6 R0 R256 + 0x8C180D05, // 0011 GETMET R6 R6 R261 + 0x7C180200, // 0012 CALL R6 1 + 0x7C140200, // 0013 CALL R5 1 + 0xA802000C, // 0014 EXBLK 0 #0022 + 0x5C180A00, // 0015 MOVE R6 R5 + 0x7C180000, // 0016 CALL R6 0 + 0x8C1C0106, // 0017 GETMET R7 R0 R262 + 0x5C240600, // 0018 MOVE R9 R3 + 0x5C280C00, // 0019 MOVE R10 R6 + 0x882C0100, // 001A GETMBR R11 R0 R256 + 0x942C1606, // 001B GETIDX R11 R11 R6 + 0x7C1C0800, // 001C CALL R7 4 + 0x741E0001, // 001D JMPT R7 #0020 + 0x74120000, // 001E JMPT R4 #0020 + 0x50100001, // 001F LDBOOL R4 0 1 + 0x50100200, // 0020 LDBOOL R4 1 0 + 0x7001FFF2, // 0021 JMP #0015 + 0x58140007, // 0022 LDCONST R5 K7 + 0xAC140200, // 0023 CATCH R5 1 0 + 0xB0080000, // 0024 RAISE 2 R0 R0 + 0x80040800, // 0025 RET 1 R4 + 0x50080000, // 0026 LDBOOL R2 0 0 + 0x80040400, // 0027 RET 1 R2 +}; + +static const bproto exec_rules_proto = { + NULL, // bgcobject *next + 8, // type + GC_CONST, // marked + 12, // nstack + 0, // nupvals + 2, // argc + 0, // varg + NULL, // bgcobject *gray + NULL, // bupvaldesc *upvals + (bvalue*) &exec_rules_ktab, // ktab + NULL, // bproto **ptab + (binstruction*) &exec_rules_code, // code + be_local_const_str(exec_rules_str_name), // name + 40, // codesize + 8, // nconst + 0, // nproto + be_local_const_str(exec_rules_str_source), // source +#if BE_DEBUG_RUNTIME_INFO /* debug information */ + NULL, // lineinfo + 0, // nlineinfo +#endif +#if BE_DEBUG_VAR_INFO + NULL, // varinfo + 0, // nvarinfo +#endif +}; + +const bclosure exec_rules_closure = { + NULL, // bgcobject *next + 36, // type + GC_CONST, // marked + 0, // nupvals + NULL, // bgcobject *gray + (bproto*) &exec_rules_proto, // proto + { NULL } // upvals +}; + +/*******************************************************************/ + + +/******************************************************************** + "def set_timer(delay,f) " + "if !self._timers self._timers=[] end " + "self._timers.push([self.millis(delay),f]) " + "end " +********************************************************************/ +/******************************************************************** +** Solidified function: set_timer +********************************************************************/ + +be_define_local_const_str(set_timer_str_name, "set_timer", 2135414533, 0, 9, 0); +be_define_local_const_str(set_timer_str_source, "string", 398550328, 0, 6, 0); +be_define_local_const_str(set_timer_str_0, "_timers", -1694866380, 0, 7, 0); +be_define_local_const_str(set_timer_str_1, "push", -2022703139, 0, 4, 0); +be_define_local_const_str(set_timer_str_2, "millis", 1214679063, 0, 6, 0); + +static const bvalue set_timer_ktab[3] = { + { { .s=be_local_const_str(set_timer_str_0) }, BE_STRING}, + { { .s=be_local_const_str(set_timer_str_1) }, BE_STRING}, + { { .s=be_local_const_str(set_timer_str_2) }, BE_STRING}, +}; + +static const uint32_t set_timer_code[16] = { + 0x880C0100, // 0000 GETMBR R3 R0 R256 + 0x740E0002, // 0001 JMPT R3 #0005 + 0x600C000A, // 0002 GETGBL R3 G10 + 0x7C0C0000, // 0003 CALL R3 0 + 0x90020003, // 0004 SETMBR R0 R256 R3 + 0x880C0100, // 0005 GETMBR R3 R0 R256 + 0x8C0C0701, // 0006 GETMET R3 R3 R257 + 0x6014000A, // 0007 GETGBL R5 G10 + 0x7C140000, // 0008 CALL R5 0 + 0x8C180102, // 0009 GETMET R6 R0 R258 + 0x5C200200, // 000A MOVE R8 R1 + 0x7C180400, // 000B CALL R6 2 + 0x40180A06, // 000C CONNECT R6 R5 R6 + 0x40180A02, // 000D CONNECT R6 R5 R2 + 0x7C0C0400, // 000E CALL R3 2 + 0x80000000, // 000F RET 0 R0 +}; + +static const bproto set_timer_proto = { + NULL, // bgcobject *next + 8, // type + GC_CONST, // marked + 9, // nstack + 0, // nupvals + 3, // argc + 0, // varg + NULL, // bgcobject *gray + NULL, // bupvaldesc *upvals + (bvalue*) &set_timer_ktab, // ktab + NULL, // bproto **ptab + (binstruction*) &set_timer_code, // code + be_local_const_str(set_timer_str_name), // name + 16, // codesize + 3, // nconst + 0, // nproto + be_local_const_str(set_timer_str_source), // source +#if BE_DEBUG_RUNTIME_INFO /* debug information */ + NULL, // lineinfo + 0, // nlineinfo +#endif +#if BE_DEBUG_VAR_INFO + NULL, // varinfo + 0, // nvarinfo +#endif +}; + +const bclosure set_timer_closure = { + NULL, // bgcobject *next + 36, // type + GC_CONST, // marked + 0, // nupvals + NULL, // bgcobject *gray + (bproto*) &set_timer_proto, // proto + { NULL } // upvals +}; + +/*******************************************************************/ + + +/******************************************************************** + // run every 50ms tick + "def run_deferred() " + "if self._timers " + "var i=0 " + "while i= 0x8000 a1 -= 0x10000 end + var a2 = b.get(2,-2) + if a2 >= 0x8000 a2 -= 0x10000 end + var a3 = b.get(4,-2) + if a3 >= 0x8000 a3 -= 0x10000 end + self.accel = [a1 * self.ares, a2 * self.ares, a3 * self.ares] + return self.accel + end + + #- returns a list of 3 gyroscopes, int as dps (degree per second) -# + def read_gyro() + var b = self.wire.read_bytes(0x68,0x43,6) + var g1 = b.get(0,-2) + if g1 >= 0x8000 g1 -= 0x10000 end + var g2 = b.get(2,-2) + if g2 >= 0x8000 g2 -= 0x10000 end + var g3 = b.get(4,-2) + if g3 >= 0x8000 g3 -= 0x10000 end + self.gyro = [int(g1 * self.gres), int(g2 * self.gres), int(g3 * self.gres)] + return self.gyro + end + + #- trigger a read every second -# + def every_second() + self.read_accel() + self.read_gyro() + end + + #- display sensor value in the web UI -# + def web_sensor() + import string + var msg = string.format( + "{s}MPU6886 acc_x{m}%f G{e}".. + "{s}MPU6886 acc_y{m}%f G{e}".. + "{s}MPU6886 acc_z{m}%f G{e}".. + "{s}MPU6886 gyr_x{m}%i dps{e}".. + "{s}MPU6886 gyr_y{m}%i dps{e}".. + "{s}MPU6886 gyr_z{m}%i dps{e}", + self.accel[0], self.accel[1], self.accel[2], self.gyro[0], self.gyro[1], self.gyro[2]) + tasmota.web_send_decimal(msg) + end + + #- add sensor value to teleperiod -# + def json_append() + import string + var ax = int(self.accel[0] * 1000) + var ay = int(self.accel[1] * 1000) + var az = int(self.accel[2] * 1000) + var msg = string.format(",\"MPU6886\":{\"AX\":%i,\"AY\":%i,\"AZ\":%i,\"GX\":%i,\"GY\":%i,\"GZ\":%i}", + ax, ay, az, self.gyro[0], self.gyro[1], self.gyro[2]) + tasmota.response_append(msg) + end + +end +mpu = MPU6886() +tasmota.add_driver(mpu) \ No newline at end of file diff --git a/tasmota/xdrv_52_0_berry_struct.ino b/tasmota/xdrv_52_0_berry_struct.ino index 22f062ba5..33e048337 100644 --- a/tasmota/xdrv_52_0_berry_struct.ino +++ b/tasmota/xdrv_52_0_berry_struct.ino @@ -22,6 +22,8 @@ #include +#define BERRY_CONSOLE_CMD_DELIMITER "\x01" + typedef LList_elt log_elt; // store the string after the header to avoid double allocation if we had used char* class BerryLog { diff --git a/tasmota/xdrv_52_3_berry_tasmota.ino b/tasmota/xdrv_52_3_berry_tasmota.ino index e29382d18..fb4c10f1c 100644 --- a/tasmota/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/xdrv_52_3_berry_tasmota.ino @@ -218,6 +218,30 @@ extern "C" { be_raise(vm, kTypeError, nullptr); } + // Response_append + int32_t l_respAppend(bvm *vm); + int32_t l_respAppend(bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 2 && be_isstring(vm, 2)) { + const char *msg = be_tostring(vm, 2); + ResponseAppend_P(PSTR("%s"), msg); + be_return_nil(vm); // Return nil when something goes wrong + } + be_raise(vm, kTypeError, nullptr); + } + + // web append with decimal conversion + int32_t l_webSendDecimal(bvm *vm); + int32_t l_webSendDecimal(bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 2 && be_isstring(vm, 2)) { + const char *msg = be_tostring(vm, 2); + WSContentSend_PD(PSTR("%s"), msg); + be_return_nil(vm); // Return nil when something goes wrong + } + be_raise(vm, kTypeError, nullptr); + } + // push the light status object on the vm stack void push_getlight(bvm *vm, uint32_t light_num) { bool data_present = false; // do we have relevant data @@ -501,17 +525,19 @@ extern "C" { extern "C" { // Berry: `log(msg:string [,log_level:int]) ->nil` // Logs the string at LOG_LEVEL_INFO (loglevel=2) + // We allow this function to be called as a method or a direct function + // if the first argument is an instance, we remove it int32_t l_logInfo(struct bvm *vm); int32_t l_logInfo(struct bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments - if (top >= 1 && be_isstring(vm, 1)) { // only 1 argument of type string accepted - const char * msg = be_tostring(vm, 1); + if (top >= 2 && be_isstring(vm, 2)) { // only 1 argument of type string accepted + const char * msg = be_tostring(vm, 2); uint32_t log_level = LOG_LEVEL_INFO; - if (top >= 2 && be_isint(vm, 2)) { - log_level = be_toint(vm, 2); + if (top >= 3 && be_isint(vm, 3)) { + log_level = be_toint(vm, 3); if (log_level > LOG_LEVEL_DEBUG_MORE) { log_level = LOG_LEVEL_DEBUG_MORE; } } - AddLog(log_level, PSTR("%s"), msg); + AddLog_P(log_level, PSTR("%s"), msg); be_return(vm); // Return } be_return_nil(vm); // Return nil when something goes wrong @@ -529,8 +555,8 @@ extern "C" { int32_t l_save(struct bvm *vm); int32_t l_save(struct bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments - if (top == 2 && be_isstring(vm, 1) && be_isclosure(vm, 2)) { // only 1 argument of type string accepted - const char *fname = be_tostring(vm, 1); + if (top == 3 && be_isstring(vm, 2) && be_isclosure(vm, 3)) { // only 1 argument of type string accepted + const char *fname = be_tostring(vm, 2); int32_t ret = be_savecode(vm, fname); be_pushint(vm, ret); be_return(vm); // Return @@ -542,14 +568,19 @@ extern "C" { // called as a replacement to Berry `print()` void berry_log(const char * berry_buf); void berry_log(const char * berry_buf) { - if (berry.repl_active) { + const char * pre_delimiter = nullptr; // do we need to prepend a delimiter if no REPL command + if (!berry.repl_active) { + // if no REPL in flight, we limit the number of logs + if (berry.log.log.length() == 0) { + pre_delimiter = BERRY_CONSOLE_CMD_DELIMITER; + } if (berry.log.log.length() >= BERRY_MAX_LOGS) { berry.log.log.remove(berry.log.log.head()); } } // AddLog(LOG_LEVEL_INFO, PSTR("[Add to log] %s"), berry_buf); - berry.log.addString(berry_buf, nullptr, "\n"); - AddLog(LOG_LEVEL_INFO, PSTR("%s"), berry_buf); + berry.log.addString(berry_buf, pre_delimiter, "\n"); + AddLog_P(LOG_LEVEL_INFO, PSTR("%s"), berry_buf); } diff --git a/tasmota/xdrv_52_7_berry_embedded.ino b/tasmota/xdrv_52_7_berry_embedded.ino index 3c7834149..051d28024 100644 --- a/tasmota/xdrv_52_7_berry_embedded.ino +++ b/tasmota/xdrv_52_7_berry_embedded.ino @@ -27,13 +27,8 @@ const char berry_prog[] = "" - //"def func(x) for i:1..x print('a') end end " - //"def testreal() return str(1.2+1) end " - //"def noop() log('noop before'); yield(); log('middle after'); yield(); log('noop after'); end " - //"log(\"foobar\") " - // create a 'ntv' module to allow functions to be registered in a safe namespace - "ntv = module('ntv') " + // "ntv = module('ntv') " // auto-import modules // // import alias @@ -42,140 +37,141 @@ const char berry_prog[] = // Phase 1 "class Tasmota: Tasmota_ntv " // for now the variables are built, need to find a way to push in Flash - "def init() " - "self._op = ['==', '!==', '=', '!=', '>=', '<=', '>', '<'] " - "self._opf = [ " - "/s1,s2-> str(s1) == str(s2)," - "/s1,s2-> str(s1) != str(s2)," - "/f1,f2-> real(f1) == real(f2)," - "/f1,f2-> real(f1) != real(f2)," - "/f1,f2-> real(f1) >= real(f2)," - "/f1,f2-> real(f1) <= real(f2)," - "/f1,f2-> real(f1) > real(f2)," - "/f1,f2-> real(f1) < real(f2)," - "] " - "self._operators = \"=<>!|\" " - "end " - // add `chars_in_string(s:string,c:string) -> int`` - // looks for any char in c, and return the position of the first chat - // or -1 if not found - "def chars_in_string(s,c) " - "for i:0..size(s)-1 " - "for j:0..size(c)-1 " - "if s[i] == c[j] return i end " - "end " - "end " - "return -1 " - "end " + // "def init() " + // "end " + // // add `chars_in_string(s:string,c:string) -> int`` + // // looks for any char in c, and return the position of the first char + // // or -1 if not found + // // inv is optional and inverses the behavior, i.e. look for chars not in the list + // "def chars_in_string(s,c,inv) " + // "var inverted = inv ? true : false " + // "for i:0..size(s)-1 " + // "var found = false " + // "for j:0..size(c)-1 " + // "if s[i] == c[j] found = true end " + // "end " + // "if inverted != found return i end " + // "end " + // "return -1 " + // "end " - // find a key in map, case insensitive, return actual key or nil if not found - "def find_key_i(m,keyi) " - "import string " - "var keyu = string.toupper(keyi) " - "if classof(m) == map " - "for k:m.keys() " - "if string.toupper(k)==keyu || keyi=='?' " - "return k " - "end " - "end " - "end " - "end " + // // find a key in map, case insensitive, return actual key or nil if not found + // "def find_key_i(m,keyi) " + // "import string " + // "var keyu = string.toupper(keyi) " + // "if classof(m) == map " + // "for k:m.keys() " + // "if string.toupper(k)==keyu || keyi=='?' " + // "return k " + // "end " + // "end " + // "end " + // "end " // # split the item when there is an operator, returns a list of (left,op,right) - // # ex: "Dimmer>50" -> ["Dimmer",tasmota_gt,"50"] - "def find_op(item) " - "import string " - "var pos = self.chars_in_string(item, self._operators) " - "if pos>=0 " - "var op_split = string.split(item,pos) " - // #print(op_split) - "var op_left = op_split[0] " - "var op_rest = op_split[1] " - // # iterate through operators - "for i: 0..size(self._op)-1 " - "var op = self._op[i] " - "if string.find(op_rest,op) == 0 " - "var op_func = self._opf[i] " - "var op_right = string.split(op_rest,size(op))[1] " - "return [op_left,op_func,op_right] " - "end " - "end " - "end " - "return [item, nil, nil] " - "end " + // // # ex: "Dimmer>50" -> ["Dimmer",tasmota_gt,"50"] + // "def find_op(item) " + // "import string " + // "var op_chars = '=<>!' " + // "var pos = self.chars_in_string(item, op_chars) " + // "if pos >= 0 " + // "var op_split = string.split(item,pos) " + // "var op_left = op_split[0] " + // "var op_rest = op_split[1] " + // "pos = self.chars_in_string(op_rest, op_chars, true) " + // "if pos >= 0 " + // "var op_split2 = string.split(op_rest,pos) " + // "var op_middle = op_split2[0] " + // "var op_right = op_split2[1] " + // "return [op_left,op_middle,op_right] " + // "end " + // "end " + // "return [item, nil, nil] " + // "end " - // Rules - "def add_rule(pat,f) " - "if !self._rules " - "self._rules={} " - "end " - "self._rules[pat] = f " - "end " + // // Rules + // "def add_rule(pat,f) " + // "if !self._rules " + // "self._rules={} " + // "end " + // "self._rules[pat] = f " + // "end " - // Rules trigger if match. return true if match, false if not - "def try_rule(ev, rule, f) " - "import string " - "var rl_list = self.find_op(rule) " - "var e=ev " - "var rl=string.split(rl_list[0],'#') " - "for it:rl " - "found=self.find_key_i(e,it) " - "if found == nil " - "return false " - "end " - "e=e[found] " - "end " - // # check if condition is true - "if rl_list[1] " - // # did we find a function - "if !rl_list[1](e,rl_list[2]) " - // # condition is not met - "return false " - "end " - "end " - "f(e,ev) " - "return true " - "end " + // // Rules trigger if match. return true if match, false if not + // "def try_rule(ev, rule, f) " + // "import string " + // "var rl_list = self.find_op(rule) " + // "var e=ev " + // "var rl=string.split(rl_list[0],'#') " + // "for it:rl " + // "found=self.find_key_i(e,it) " + // "if found == nil return false end " + // "e=e[found] " + // "end " + // "var op=rl_list[1]" + // "var op2=rl_list[2]" + // "if op " + // "if op=='==' " + // "if str(e) != str(op2) return false end " + // "elif op=='!==' " + // "if str(e) == str(op2) return false end " + // "elif op=='=' " + // "if real(e) != real(op2) return false end " + // "elif op=='!=' " + // "if real(e) == real(op2) return false end " + // "elif op=='>' " + // "if real(e) <= real(op2) return false end " + // "elif op=='>=' " + // "if real(e) < real(op2) return false end " + // "elif op=='<' " + // "if real(e) >= real(op2) return false end " + // "elif op=='<=' " + // "if real(e) > real(op2) return false end " + // "end " + // "end " + // "f(e,ev) " + // "return true " + // "end " - // Run rules, i.e. check each individual rule - // Returns true if at least one rule matched, false if none - "def exec_rules(ev_json) " - "if self._rules " - "import json " - "var ev = json.load(ev_json) " - "var ret = false " - "if ev == nil " - "print('BRY: ERROR, bad json: '+ev_json, 3) " - "else " - "for r: self._rules.keys() " - "ret = self.try_rule(ev,r,self._rules[r]) || ret " - "end " - "end " - "return ret " - "end " - "return false " - "end " + // // Run rules, i.e. check each individual rule + // // Returns true if at least one rule matched, false if none + // "def exec_rules(ev_json) " + // "if self._rules " + // "import json " + // "var ev = json.load(ev_json) " + // "var ret = false " + // "if ev == nil " + // "print('BRY: ERROR, bad json: '+ev_json, 3) " + // "else " + // "for r: self._rules.keys() " + // "ret = self.try_rule(ev,r,self._rules[r]) || ret " + // "end " + // "end " + // "return ret " + // "end " + // "return false " + // "end " - "def set_timer(delay,f) " - "if !self._timers self._timers=[] end " - "self._timers.push([self.millis(delay),f]) " - "end " + // "def set_timer(delay,f) " + // "if !self._timers self._timers=[] end " + // "self._timers.push([self.millis(delay),f]) " + // "end " - // run every 50ms tick - "def run_deferred() " - "if self._timers " - "var i=0 " - "while i -#define BERRY_CONSOLE_CMD_DELIMITER "\x01" +extern "C" { + extern void be_load_custom_libs(bvm *vm); +} const char kBrCommands[] PROGMEM = D_PRFX_BR "|" // prefix D_CMND_BR_RUN "|" D_CMND_BR_RESET @@ -179,8 +181,9 @@ int32_t callBerryEventDispatcher(const char *type, const char *cmd, int32_t idx, be_pushstring(berry.vm, payload != nullptr ? payload : "{}"); // empty json be_pcall(berry.vm, 5); // 5 arguments be_pop(berry.vm, 5); - if (be_isint(berry.vm, -1)) { - ret = be_toint(berry.vm, -1); + if (be_isint(berry.vm, -1) || be_isbool(berry.vm, -1)) { + if (be_isint(berry.vm, -1)) { ret = be_toint(berry.vm, -1); } + if (be_isbool(berry.vm, -1)) { ret = be_tobool(berry.vm, -1); } } } be_pop(berry.vm, 1); // remove method @@ -238,11 +241,12 @@ void BrReset(void) { do { berry.vm = be_vm_new(); /* create a virtual machine instance */ be_set_obs_hook(berry.vm, &BerryObservability); + be_load_custom_libs(berry.vm); // AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry VM created, RAM used=%u"), be_gc_memcount(berry.vm)); // Register functions - be_regfunc(berry.vm, PSTR("log"), l_logInfo); - be_regfunc(berry.vm, PSTR("save"), l_save); + // be_regfunc(berry.vm, PSTR("log"), l_logInfo); + // be_regfunc(berry.vm, PSTR("save"), l_save); // AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry function registered, RAM used=%u"), be_gc_memcount(berry.vm)); @@ -727,7 +731,7 @@ bool Xdrv52(uint8_t function) callBerryEventDispatcher(PSTR("web_add_main_button"), nullptr, 0, nullptr); break; case FUNC_WEB_ADD_HANDLER: - callBerryEventDispatcher(PSTR("web_add_handler"), nullptr, 0, nullptr); + // callBerryEventDispatcher(PSTR("web_add_handler"), nullptr, 0, nullptr); WebServer_on(PSTR("/bs"), HandleBerryConsole); break; #endif // USE_WEBSERVER @@ -739,7 +743,7 @@ bool Xdrv52(uint8_t function) break; case FUNC_JSON_APPEND: - callBerryEventDispatcher(PSTR("json_aooend"), nullptr, 0, nullptr); + callBerryEventDispatcher(PSTR("json_append"), nullptr, 0, nullptr); break; case FUNC_BUTTON_PRESSED: