diff --git a/lib/libesp32/Berry-0.1.10/src/be_solidifylib.c b/lib/libesp32/Berry-0.1.10/src/be_solidifylib.c index cd355bc3d..56304bea3 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_solidifylib.c +++ b/lib/libesp32/Berry-0.1.10/src/be_solidifylib.c @@ -45,46 +45,39 @@ static const char * m_type_ktab(int type) } } -static void m_solidify_closure(bvm *vm, bclosure *cl, int builtins) -{ - bproto *pr = cl->proto; - const char * func_name = str(pr->name); +static void m_solidify_proto(bvm *vm, bproto *pr, const char * func_name, int builtins) +{ + // 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); + if (pr->nproto > 0) { + for (int32_t i = 0; i < pr->nproto; i++) { + size_t sub_len = strlen(func_name) + 10; + char sub_name[sub_len]; + snprintf(sub_name, sizeof(sub_name), "%s_%d", func_name, i); + m_solidify_proto(vm, pr->ptab[i], sub_name, builtins); + } + } - // 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("\n/********** Solidified proto: %s */\n", func_name); - // 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); + if (pr->nproto > 0) { + logfmt("static const bproto *%s_subproto[%i] = {\n", func_name, pr->nproto); + for (int32_t i = 0; i < pr->nproto; i++) { + logfmt(" &%s_%d_proto,\n", func_name, i); + // logfmt(" be_local_const_upval(%i, %i),\n", pr->upvals[i].instack, pr->upvals[i].idx); TODO + } + logfmt("};\n\n"); + } - // 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"); + if (pr->nupvals > 0) { + logfmt("static const bupvaldesc %s_upvals[%i] = {\n", func_name, pr->nupvals); + for (int32_t i = 0; i < pr->nupvals; i++) { + logfmt(" be_local_const_upval(%i, %i),\n", pr->upvals[i].instack, pr->upvals[i].idx); + // logfmt("// upval[%d] = { .instack = %i, .idx = %i }\n", i, pr->upvals[i].instack, pr->upvals[i].idx); + } + 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", @@ -107,30 +100,32 @@ static void m_solidify_closure(bvm *vm, bclosure *cl, int builtins) } 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); + if (pr->nconst > 0) { + 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("};\n\n"); logfmt("static const uint32_t %s_code[%i] = {\n", func_name, pr->codesize); for (int pc = 0; pc < pr->codesize; pc++) { @@ -150,52 +145,28 @@ static void m_solidify_closure(bvm *vm, bclosure *cl, int builtins) } 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("be_define_local_proto(%s, %d, %d, %d, %d, %d);\n", + func_name, pr->nstack, pr->argc, (pr->nconst > 0) ? 1 : 0, (pr->nproto > 0) ? 1 : 0, (pr->nupvals > 0) ? 1 : 0); +} + +static void m_solidify_closure(bvm *vm, bclosure *cl, int builtins) +{ + bproto *pr = cl->proto; + const char * func_name = str(pr->name); + + if (cl->nupvals > 0) { + be_raise(vm, "internal_error", "Unsupported upvals in closure"); } - 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"); + + logfmt("\n"); + logfmt("/********************************************************************\n"); + logfmt("** Solidified function: %s\n", func_name); + logfmt("********************************************************************/\n"); + + m_solidify_proto(vm, pr, func_name, builtins); // 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("be_define_local_closure(%s);\n\n", func_name); logfmt("/*******************************************************************/\n\n"); } diff --git a/lib/libesp32/Berry-0.1.10/src/berry.h b/lib/libesp32/Berry-0.1.10/src/berry.h index 25e9f3c85..760ec2961 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 static + #define BERRY_LOCAL #endif #ifdef __cplusplus @@ -252,7 +252,7 @@ typedef struct bntvmodule { /* 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 = { \ + static const bcstring be_local_const_str_##_name = { \ .next = (bgcobject *)NULL, \ .type = BE_STRING, \ .marked = GC_CONST, \ @@ -264,6 +264,68 @@ typedef struct bntvmodule { #define be_local_const_str(_name) (bstring*) &be_local_const_str_##_name +/* conditional macro see https://stackoverflow.com/questions/11632219/c-preprocessor-macro-specialisation-based-on-an-argument */ +#define BE_IIF(cond) BE_IIF_ ## cond +#define BE_IIF_0(t, f) f +#define BE_IIF_1(t, f) t + +#if BE_DEBUG_VAR_INFO + #define be_local_const_upval(ins, idx) { "", ins, idx } +#else + #define be_local_const_upval(ins, idx) { ins, idx } +#endif + +/* conditional block in bproto depending on compilation options */ +#if BE_DEBUG_RUNTIME_INFO + #define PROTO_RUNTIME_BLOCK \ + NULL, /* varinfo */ \ + 0, /* nvarinfo */ +#else + #define PROTO_RUNTIME_BLOCK +#endif +#if BE_DEBUG_VAR_INFO + #define PROTO_VAR_INFO_BLOCK\ + NULL, /* varinfo */ \ + 0, /* nvarinfo */ +#else + #define PROTO_VAR_INFO_BLOCK +#endif + +/* define bproto */ +#define be_define_local_proto(_name, _nstack, _argc, _is_const, _is_subproto, _is_upval) \ + static const bproto _name##_proto = { \ + NULL, /* bgcobject *next */ \ + 8, /* type BE_PROTO */ \ + GC_CONST, /* marked outside of GC */ \ + (_nstack), /* nstack */ \ + BE_IIF(_is_upval)(sizeof(_name##_upvals)/sizeof(bupvaldesc),0),/* nupvals */ \ + (_argc), /* argc */ \ + 0, /* varg */ \ + NULL, /* bgcobject *gray */ \ + BE_IIF(_is_upval)((bupvaldesc*)&_name##_upvals,NULL), /* bupvaldesc *upvals */ \ + BE_IIF(_is_const)((bvalue*)&_name##_ktab,NULL), /* ktab */ \ + BE_IIF(_is_subproto)((struct bproto**)&_name##_subproto,NULL),/* bproto **ptab */ \ + (binstruction*) &_name##_code, /* code */ \ + be_local_const_str(_name##_str_name), /* name */ \ + sizeof(_name##_code)/sizeof(uint32_t), /* codesize */ \ + BE_IIF(_is_const)(sizeof(_name##_ktab)/sizeof(bvalue),0),/* nconst */ \ + BE_IIF(_is_subproto)(sizeof(_name##_subproto)/sizeof(bproto*),0),/* proto */ \ + be_local_const_str(_name##_str_source), /* source */ \ + PROTO_RUNTIME_BLOCK \ + PROTO_VAR_INFO_BLOCK \ + } + +#define be_define_local_closure(_name) \ + const bclosure _name##_closure = { \ + NULL, /* bgcobject *next */ \ + 36, /* type BE_CLOSURE */ \ + GC_CONST, /* marked */ \ + 0, /* nupvals */ \ + NULL, /* bgcobject *gray */ \ + (bproto*) &_name##_proto, /* proto */ \ + { NULL } /* upvals */ \ + } + /* debug hook typedefs */ #define BE_HOOK_LINE 1 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 index 4e9b8cce8..fd9c2ccbb 100644 --- a/lib/libesp32/Berry-0.1.10/src/port/be_driverlib.c +++ b/lib/libesp32/Berry-0.1.10/src/port/be_driverlib.c @@ -5,6 +5,77 @@ * *******************************************************************/ #include "be_object.h" +#include "be_string.h" +#include "be_gc.h" + +extern int d_getTasmotaGlob(bvm *vm); + + +/******************************************************************** + "class Driver2 : Driver " + "def add_cmd(c, f) " + "var tasmota = self.get_tasmota() " + "tasmota.add_cmd(c, / cmd, idx, payload, payload_json -> f(self, cmd, idx, payload, payload_json)) " + "end " + "end " + "Driver = Driver2 " +********************************************************************/ +/******************************************************************** +** Solidified function: add_cmd +********************************************************************/ + +/********** Solidified proto: add_cmd_0 */ +static const bupvaldesc add_cmd_0_upvals[2] = { + be_local_const_upval(1, 2), + be_local_const_upval(1, 0), +}; + +be_define_local_const_str(add_cmd_0_str_name, "add_cmd_0", 607256038, 0, 8, 0); +be_define_local_const_str(add_cmd_0_str_source, "input", -103256197, 0, 5, 0); + +static const uint32_t add_cmd_0_code[8] = { + 0x68100000, // 0000 GETUPV R4 U0 + 0x68140001, // 0001 GETUPV R5 U1 + 0x5C180000, // 0002 MOVE R6 R0 + 0x5C1C0200, // 0003 MOVE R7 R1 + 0x5C200400, // 0004 MOVE R8 R2 + 0x5C240600, // 0005 MOVE R9 R3 + 0x7C100A00, // 0006 CALL R4 5 + 0x80040800, // 0007 RET 1 R4 +}; + +be_define_local_proto(add_cmd_0, 10, 4, 0, 0, 1); + +/********** Solidified proto: add_cmd */ +static const bproto *add_cmd_subproto[1] = { + &add_cmd_0_proto, +}; + +be_define_local_const_str(add_cmd_str_name, "add_cmd", -933336417, 0, 7, 0); +be_define_local_const_str(add_cmd_str_source, "input", -103256197, 0, 5, 0); +be_define_local_const_str(add_cmd_str_0, "get_tasmota", 334356779, 0, 11, 0); +be_define_local_const_str(add_cmd_str_1, "add_cmd", -933336417, 0, 7, 0); + +static const bvalue add_cmd_ktab[2] = { + { { .s=be_local_const_str(add_cmd_str_0) }, BE_STRING}, + { { .s=be_local_const_str(add_cmd_str_1) }, BE_STRING}, +}; + +static const uint32_t add_cmd_code[8] = { + 0x8C0C0100, // 0000 GETMET R3 R0 R256 + 0x7C0C0200, // 0001 CALL R3 1 + 0x8C100701, // 0002 GETMET R4 R3 R257 + 0x5C180200, // 0003 MOVE R6 R1 + 0x841C0000, // 0004 CLOSURE R7 P0 + 0x7C100600, // 0005 CALL R4 3 + 0xA0000000, // 0006 CLOSE 0 + 0x80000000, // 0007 RET 0 R0 +}; + +be_define_local_proto(add_cmd, 8, 3, 1, 1, 0); +be_define_local_closure(add_cmd); + +/*******************************************************************/ // #if !BE_USE_PRECOMPILED_OBJECT #if 1 // TODO we will do pre-compiled later @@ -19,6 +90,11 @@ void be_load_driverlib(bvm *vm) { "web_sensor", NULL }, { "json_append", NULL }, { "button_pressed", NULL }, + + { "get_tasmota", d_getTasmotaGlob }, + + { NULL, (bntvfunc) BE_CLOSURE }, /* mark section for berry closures */ + { "add_cmd", (bntvfunc) &add_cmd_closure }, { NULL, NULL } }; diff --git a/tasmota/xdrv_52_3_berry_tasmota.ino b/tasmota/xdrv_52_3_berry_tasmota.ino index 89ea65858..e22330a7e 100644 --- a/tasmota/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/xdrv_52_3_berry_tasmota.ino @@ -361,4 +361,21 @@ void berry_log(const char * berry_buf) { } +/*********************************************************************************************\ + * Helper function for `Driver` class + * + * get_tasmota() -> tasmota instance from globals + * allows to use solidified methods refering to the global object `tasmota` + * +\*********************************************************************************************/ +extern "C" { + + int32_t d_getTasmotaGlob(struct bvm *vm); + int32_t d_getTasmotaGlob(struct bvm *vm) { + be_getglobal(berry.vm, PSTR("tasmota")); + be_return(vm); // Return + } + +} + #endif // USE_BERRY diff --git a/tasmota/xdrv_52_7_berry_embedded.ino b/tasmota/xdrv_52_7_berry_embedded.ino index cfcce38e2..f1d44250a 100644 --- a/tasmota/xdrv_52_7_berry_embedded.ino +++ b/tasmota/xdrv_52_7_berry_embedded.ino @@ -352,6 +352,15 @@ const char berry_prog[] = "end " + // // Monkey patch `Driver` class - To be continued + // "class Driver2 : Driver " + // "def add_cmd(c, f) " + // "var tasmota = self.get_tasmota() " + // "tasmota.add_cmd(c, / cmd, idx, payload, payload_json -> f(self, cmd, idx, payload, payload_json)) " + // "end " + // "end " + // "Driver = Driver2 " + // Instantiate tasmota object "tasmota = Tasmota() " "def log(m,l) tasmota.log(m,l) end " @@ -380,12 +389,16 @@ const char berry_prog[] = // "end " // "end " +#ifdef USE_I2C "tasmota.wire1 = Wire(1) " "tasmota.wire2 = Wire(2) " "wire1 = tasmota.wire1 " "wire2 = tasmota.wire2 " +#endif // USE_I2C + // auto-import gpio "import gpio " + #ifdef USE_LIGHT "import light " #endif // USE_LIGHT