mirror of https://github.com/arendst/Tasmota.git
Merge pull request #11667 from s-hadinger/berry_apr_11_2
Berry driver.add_cmd()
This commit is contained in:
commit
17b217b950
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue