Merge pull request #11667 from s-hadinger/berry_apr_11_2

Berry driver.add_cmd()
This commit is contained in:
Theo Arends 2021-04-11 16:44:03 +02:00 committed by GitHub
commit 17b217b950
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 241 additions and 102 deletions

View File

@ -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");
}

View File

@ -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

View File

@ -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 }
};

View File

@ -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

View File

@ -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