mirror of https://github.com/arendst/Tasmota.git
Berry upgrade to latest changes
This commit is contained in:
parent
228593c092
commit
5ab0081f47
|
@ -608,23 +608,18 @@ BERRY_API bbool be_getbuiltin(bvm *vm, const char *name)
|
||||||
|
|
||||||
BERRY_API bbool be_setmember(bvm *vm, int index, const char *k)
|
BERRY_API bbool be_setmember(bvm *vm, int index, const char *k)
|
||||||
{
|
{
|
||||||
int res = BE_NIL;
|
|
||||||
bvalue *o = be_indexof(vm, index);
|
bvalue *o = be_indexof(vm, index);
|
||||||
|
bvalue *v = be_indexof(vm, -1);
|
||||||
if (var_isinstance(o)) {
|
if (var_isinstance(o)) {
|
||||||
bstring *key = be_newstr(vm, k);
|
bstring *key = be_newstr(vm, k);
|
||||||
bvalue *v = be_indexof(vm, -1);
|
|
||||||
binstance *obj = var_toobj(o);
|
binstance *obj = var_toobj(o);
|
||||||
res = be_instance_setmember(vm, obj, key, v);
|
return be_instance_setmember(vm, obj, key, v);
|
||||||
} else if (var_ismodule(o)) {
|
} else if (var_ismodule(o)) {
|
||||||
bstring *key = be_newstr(vm, k);
|
bstring *key = be_newstr(vm, k);
|
||||||
bmodule *mod = var_toobj(o);
|
bmodule *mod = var_toobj(o);
|
||||||
bvalue *v = be_module_bind(vm, mod, key);
|
return be_module_setmember(vm, mod, key, v);
|
||||||
if (v) {
|
|
||||||
*v = *be_indexof(vm, -1);
|
|
||||||
return btrue;
|
|
||||||
}
|
}
|
||||||
}
|
return bfalse;
|
||||||
return res != BE_NIL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BERRY_API bbool be_copy(bvm *vm, int index)
|
BERRY_API bbool be_copy(bvm *vm, int index)
|
||||||
|
@ -650,16 +645,15 @@ static int ins_member(bvm *vm, int index, const char *k, bbool onlyins)
|
||||||
if (var_isinstance(o)) {
|
if (var_isinstance(o)) {
|
||||||
binstance *obj = var_toobj(o);
|
binstance *obj = var_toobj(o);
|
||||||
type = be_instance_member(vm, obj, be_newstr(vm, k), top);
|
type = be_instance_member(vm, obj, be_newstr(vm, k), top);
|
||||||
if (type == BE_NONE) {
|
} else if (var_isclass(o) && !onlyins) {
|
||||||
type = BE_NIL;
|
bclass *cl = var_toobj(o);
|
||||||
}
|
type = be_class_member(vm, cl, be_newstr(vm, k), top);
|
||||||
} else if (var_ismodule(o) && !onlyins) {
|
} else if (var_ismodule(o) && !onlyins) {
|
||||||
bmodule *module = var_toobj(o);
|
bmodule *module = var_toobj(o);
|
||||||
bvalue *v = be_module_attr(vm, module, be_newstr(vm, k));
|
type = be_module_attr(vm, module, be_newstr(vm, k), top);
|
||||||
if (v != NULL) {
|
|
||||||
*top = *v;
|
|
||||||
type = v->type;
|
|
||||||
}
|
}
|
||||||
|
if (type == BE_NONE) {
|
||||||
|
type = BE_NIL;
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#define MAGIC_NUMBER1 0xBE
|
#define MAGIC_NUMBER1 0xBE
|
||||||
#define MAGIC_NUMBER2 0xCD
|
#define MAGIC_NUMBER2 0xCD
|
||||||
#define MAGIC_NUMBER3 0xFE
|
#define MAGIC_NUMBER3 0xFE
|
||||||
#define BYTECODE_VERSION 1
|
#define BYTECODE_VERSION 2
|
||||||
|
|
||||||
#define USE_64BIT_INT (BE_INTGER_TYPE == 2 \
|
#define USE_64BIT_INT (BE_INTGER_TYPE == 2 \
|
||||||
|| BE_INTGER_TYPE == 1 && LONG_MAX == 9223372036854775807L)
|
|| BE_INTGER_TYPE == 1 && LONG_MAX == 9223372036854775807L)
|
||||||
|
@ -179,12 +179,18 @@ static void save_value(bvm *vm, void *fp, bvalue *v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void save_bytecode(void *fp, bproto *proto)
|
static void save_bytecode(bvm *vm, void *fp, bproto *proto)
|
||||||
{
|
{
|
||||||
|
int forbid_gbl = comp_is_named_gbl(vm);
|
||||||
binstruction *code = proto->code, *end;
|
binstruction *code = proto->code, *end;
|
||||||
save_long(fp, (uint32_t)proto->codesize);
|
save_long(fp, (uint32_t)proto->codesize);
|
||||||
for (end = code + proto->codesize; code < end; ++code) {
|
for (end = code + proto->codesize; code < end; ++code) {
|
||||||
save_long(fp, (uint32_t)*code);
|
save_long(fp, (uint32_t)*code);
|
||||||
|
if (forbid_gbl) { /* we are saving only named globals, so make sure we don't save OP_GETGBL or OP_SETGBL */
|
||||||
|
if ((uint32_t)*code == OP_GETGBL || (uint32_t)*code == OP_SETGBL) {
|
||||||
|
be_raise(vm, "internal_error", "GETGBL/SETGBL found when saving with named globals");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +229,9 @@ static void save_proto(bvm *vm, void *fp, bproto *proto)
|
||||||
save_string(fp, proto->source); /* source */
|
save_string(fp, proto->source); /* source */
|
||||||
save_byte(fp, proto->argc); /* argc */
|
save_byte(fp, proto->argc); /* argc */
|
||||||
save_byte(fp, proto->nstack); /* nstack */
|
save_byte(fp, proto->nstack); /* nstack */
|
||||||
save_bytecode(fp, proto); /* bytecode */
|
save_byte(fp, proto->varg); /* varg */
|
||||||
|
save_byte(fp, 0x00); /* reserved */
|
||||||
|
save_bytecode(vm, fp, proto); /* bytecode */
|
||||||
save_constants(vm, fp, proto); /* constant */
|
save_constants(vm, fp, proto); /* constant */
|
||||||
save_proto_table(vm, fp, proto); /* proto table */
|
save_proto_table(vm, fp, proto); /* proto table */
|
||||||
save_upvals(fp, proto); /* upvals description table */
|
save_upvals(fp, proto); /* upvals description table */
|
||||||
|
@ -253,8 +261,13 @@ static void save_globals(bvm *vm, void *fp)
|
||||||
static void save_global_info(bvm *vm, void *fp)
|
static void save_global_info(bvm *vm, void *fp)
|
||||||
{
|
{
|
||||||
save_long(fp, be_builtin_count(vm));
|
save_long(fp, be_builtin_count(vm));
|
||||||
|
if (comp_is_named_gbl(vm)) {
|
||||||
|
/* named globals only so no need to save current globals */
|
||||||
|
save_long(fp, 0);
|
||||||
|
} else {
|
||||||
save_long(fp, be_global_count(vm));
|
save_long(fp, be_global_count(vm));
|
||||||
save_globals(vm, fp);
|
save_globals(vm, fp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void be_bytecode_save(bvm *vm, const char *filename, bproto *proto)
|
void be_bytecode_save(bvm *vm, const char *filename, bproto *proto)
|
||||||
|
@ -273,7 +286,7 @@ void be_bytecode_save(bvm *vm, const char *filename, bproto *proto)
|
||||||
#endif /* BE_USE_BYTECODE_SAVER */
|
#endif /* BE_USE_BYTECODE_SAVER */
|
||||||
|
|
||||||
#if BE_USE_BYTECODE_LOADER
|
#if BE_USE_BYTECODE_LOADER
|
||||||
static void load_proto(bvm *vm, void *fp, bproto **proto, int info);
|
static void load_proto(bvm *vm, void *fp, bproto **proto, int info, int version);
|
||||||
|
|
||||||
static uint8_t load_byte(void *fp)
|
static uint8_t load_byte(void *fp)
|
||||||
{
|
{
|
||||||
|
@ -313,9 +326,13 @@ static int load_head(void *fp)
|
||||||
res = buffer[0] == MAGIC_NUMBER1 &&
|
res = buffer[0] == MAGIC_NUMBER1 &&
|
||||||
buffer[1] == MAGIC_NUMBER2 &&
|
buffer[1] == MAGIC_NUMBER2 &&
|
||||||
buffer[2] == MAGIC_NUMBER3 &&
|
buffer[2] == MAGIC_NUMBER3 &&
|
||||||
buffer[3] == BYTECODE_VERSION &&
|
buffer[3] <= BYTECODE_VERSION &&
|
||||||
buffer[4] == vm_sizeinfo();
|
buffer[4] == vm_sizeinfo();
|
||||||
return res;
|
if (res) {
|
||||||
|
return buffer[3];
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bbool be_bytecode_check(const char *path)
|
bbool be_bytecode_check(const char *path)
|
||||||
|
@ -385,7 +402,7 @@ static bstring* cache_string(bvm *vm, void *fp)
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load_class(bvm *vm, void *fp, bvalue *v)
|
static void load_class(bvm *vm, void *fp, bvalue *v, int version)
|
||||||
{
|
{
|
||||||
int nvar, count;
|
int nvar, count;
|
||||||
bclass *c = be_newclass(vm, NULL, NULL);
|
bclass *c = be_newclass(vm, NULL, NULL);
|
||||||
|
@ -399,7 +416,7 @@ static void load_class(bvm *vm, void *fp, bvalue *v)
|
||||||
value = vm->top;
|
value = vm->top;
|
||||||
var_setproto(value, NULL);
|
var_setproto(value, NULL);
|
||||||
be_incrtop(vm);
|
be_incrtop(vm);
|
||||||
load_proto(vm, fp, (bproto**)&var_toobj(value), -3);
|
load_proto(vm, fp, (bproto**)&var_toobj(value), -3, version);
|
||||||
be_method_bind(vm, c, name, var_toobj(value));
|
be_method_bind(vm, c, name, var_toobj(value));
|
||||||
be_stackpop(vm, 2); /* pop the cached string and proto */
|
be_stackpop(vm, 2); /* pop the cached string and proto */
|
||||||
}
|
}
|
||||||
|
@ -410,13 +427,13 @@ static void load_class(bvm *vm, void *fp, bvalue *v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load_value(bvm *vm, void *fp, bvalue *v)
|
static void load_value(bvm *vm, void *fp, bvalue *v, int version)
|
||||||
{
|
{
|
||||||
switch (load_byte(fp)) {
|
switch (load_byte(fp)) {
|
||||||
case BE_INT: var_setint(v, load_int(fp)); break;
|
case BE_INT: var_setint(v, load_int(fp)); break;
|
||||||
case BE_REAL: var_setreal(v, load_real(fp)); break;
|
case BE_REAL: var_setreal(v, load_real(fp)); break;
|
||||||
case BE_STRING: var_setstr(v, load_string(vm, fp)); break;
|
case BE_STRING: var_setstr(v, load_string(vm, fp)); break;
|
||||||
case BE_CLASS: load_class(vm, fp, v); break;
|
case BE_CLASS: load_class(vm, fp, v, version); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -449,7 +466,7 @@ static void load_bytecode(bvm *vm, void *fp, bproto *proto, int info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load_constant(bvm *vm, void *fp, bproto *proto)
|
static void load_constant(bvm *vm, void *fp, bproto *proto, int version)
|
||||||
{
|
{
|
||||||
int size = (int)load_long(fp); /* nconst */
|
int size = (int)load_long(fp); /* nconst */
|
||||||
if (size) {
|
if (size) {
|
||||||
|
@ -458,12 +475,12 @@ static void load_constant(bvm *vm, void *fp, bproto *proto)
|
||||||
proto->ktab = v;
|
proto->ktab = v;
|
||||||
proto->nconst = size;
|
proto->nconst = size;
|
||||||
for (end = v + size; v < end; ++v) {
|
for (end = v + size; v < end; ++v) {
|
||||||
load_value(vm, fp, v);
|
load_value(vm, fp, v, version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load_proto_table(bvm *vm, void *fp, bproto *proto)
|
static void load_proto_table(bvm *vm, void *fp, bproto *proto, int version)
|
||||||
{
|
{
|
||||||
int size = (int)load_long(fp); /* proto count */
|
int size = (int)load_long(fp); /* proto count */
|
||||||
if (size) {
|
if (size) {
|
||||||
|
@ -472,7 +489,7 @@ static void load_proto_table(bvm *vm, void *fp, bproto *proto)
|
||||||
proto->ptab = p;
|
proto->ptab = p;
|
||||||
proto->nproto = size;
|
proto->nproto = size;
|
||||||
while (size--) {
|
while (size--) {
|
||||||
load_proto(vm, fp, p++, -1);
|
load_proto(vm, fp, p++, -1, version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -492,16 +509,20 @@ static void load_upvals(bvm *vm, void *fp, bproto *proto)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load_proto(bvm *vm, void *fp, bproto **proto, int info)
|
static void load_proto(bvm *vm, void *fp, bproto **proto, int info, int version)
|
||||||
{
|
{
|
||||||
*proto = be_newproto(vm);
|
*proto = be_newproto(vm);
|
||||||
(*proto)->name = load_string(vm, fp);
|
(*proto)->name = load_string(vm, fp);
|
||||||
(*proto)->source = load_string(vm, fp);
|
(*proto)->source = load_string(vm, fp);
|
||||||
(*proto)->argc = load_byte(fp);
|
(*proto)->argc = load_byte(fp);
|
||||||
(*proto)->nstack = load_byte(fp);
|
(*proto)->nstack = load_byte(fp);
|
||||||
|
if (version > 1) {
|
||||||
|
(*proto)->varg = load_byte(fp);
|
||||||
|
load_byte(fp); /* discard reserved byte */
|
||||||
|
}
|
||||||
load_bytecode(vm, fp, *proto, info);
|
load_bytecode(vm, fp, *proto, info);
|
||||||
load_constant(vm, fp, *proto);
|
load_constant(vm, fp, *proto, version);
|
||||||
load_proto_table(vm, fp, *proto);
|
load_proto_table(vm, fp, *proto, version);
|
||||||
load_upvals(vm, fp, *proto);
|
load_upvals(vm, fp, *proto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,7 +531,7 @@ void load_global_info(bvm *vm, void *fp)
|
||||||
int i;
|
int i;
|
||||||
int bcnt = (int)load_long(fp); /* builtin count */
|
int bcnt = (int)load_long(fp); /* builtin count */
|
||||||
int gcnt = (int)load_long(fp); /* global count */
|
int gcnt = (int)load_long(fp); /* global count */
|
||||||
if (bcnt != be_builtin_count(vm)) {
|
if (bcnt > be_builtin_count(vm)) {
|
||||||
bytecode_error(vm, be_pushfstring(vm,
|
bytecode_error(vm, be_pushfstring(vm,
|
||||||
"inconsistent number of builtin objects."));
|
"inconsistent number of builtin objects."));
|
||||||
}
|
}
|
||||||
|
@ -530,16 +551,19 @@ bclosure* be_bytecode_load(bvm *vm, const char *filename)
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
bytecode_error(vm, be_pushfstring(vm,
|
bytecode_error(vm, be_pushfstring(vm,
|
||||||
"can not open file '%s'.", filename));
|
"can not open file '%s'.", filename));
|
||||||
} else if (load_head(fp)) {
|
} else {
|
||||||
|
int version = load_head(fp);
|
||||||
|
if (version) {
|
||||||
bclosure *cl = be_newclosure(vm, 0);
|
bclosure *cl = be_newclosure(vm, 0);
|
||||||
var_setclosure(vm->top, cl);
|
var_setclosure(vm->top, cl);
|
||||||
be_stackpush(vm);
|
be_stackpush(vm);
|
||||||
load_global_info(vm, fp);
|
load_global_info(vm, fp);
|
||||||
load_proto(vm, fp, &cl->proto, -1);
|
load_proto(vm, fp, &cl->proto, -1, version);
|
||||||
be_stackpop(vm, 2); /* pop the closure and list */
|
be_stackpop(vm, 2); /* pop the closure and list */
|
||||||
be_fclose(fp);
|
be_fclose(fp);
|
||||||
return cl;
|
return cl;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
bytecode_error(vm, be_pushfstring(vm,
|
bytecode_error(vm, be_pushfstring(vm,
|
||||||
"invalid bytecode file '%s'.", filename));
|
"invalid bytecode file '%s'.", filename));
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -241,20 +241,38 @@ bbool be_class_newobj(bvm *vm, bclass *c, bvalue *reg, int argc, int mode)
|
||||||
/* Input: none of `obj`, `name` and `dst` may not be NULL */
|
/* Input: none of `obj`, `name` and `dst` may not be NULL */
|
||||||
/* Returns the type of the member or BE_NONE if member not found */
|
/* Returns the type of the member or BE_NONE if member not found */
|
||||||
/* TODO need to support synthetic members */
|
/* TODO need to support synthetic members */
|
||||||
int be_instance_member(bvm *vm, binstance *obj, bstring *name, bvalue *dst)
|
int be_instance_member(bvm *vm, binstance *instance, bstring *name, bvalue *dst)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
be_assert(name != NULL);
|
be_assert(name != NULL);
|
||||||
obj = instance_member(vm, obj, name, dst);
|
binstance * obj = instance_member(vm, instance, name, dst);
|
||||||
type = var_type(dst);
|
type = var_type(dst);
|
||||||
if (obj && type == MT_VARIABLE) {
|
if (obj && type == MT_VARIABLE) {
|
||||||
*dst = obj->members[dst->v.i];
|
*dst = obj->members[dst->v.i];
|
||||||
}
|
}
|
||||||
if (obj) {
|
if (obj) {
|
||||||
return type;
|
return type;
|
||||||
} else {
|
} else { /* if no method found, try virtual */
|
||||||
return BE_NONE;
|
/* get method 'member' */
|
||||||
|
obj = instance_member(vm, instance, str_literal(vm, "member"), vm->top);
|
||||||
|
if (obj && basetype(var_type(vm->top)) == BE_FUNCTION) {
|
||||||
|
bvalue *top = vm->top;
|
||||||
|
var_setinstance(&top[1], instance);
|
||||||
|
var_setstr(&top[2], name);
|
||||||
|
vm->top += 3; /* prevent gc collection results */
|
||||||
|
be_dofunc(vm, top, 2); /* call method 'member' */
|
||||||
|
vm->top -= 3;
|
||||||
|
*dst = *vm->top; /* copy result to R(A) */
|
||||||
|
if (obj && var_type(dst) == MT_VARIABLE) {
|
||||||
|
*dst = obj->members[dst->v.i];
|
||||||
}
|
}
|
||||||
|
type = var_type(dst);
|
||||||
|
if (type != BE_NIL) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int be_class_member(bvm *vm, bclass *obj, bstring *name, bvalue *dst)
|
int be_class_member(bvm *vm, bclass *obj, bstring *name, bvalue *dst)
|
||||||
|
|
|
@ -251,7 +251,7 @@ static int newconst(bfuncinfo *finfo, bvalue *k)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find constant by value and return constant number, or -1 if constant does not exist */
|
/* Find constant by value and return constant number, or -1 if constant does not exist */
|
||||||
/* The search is linear and lilited to 50 elements for performance reasons */
|
/* The search is linear and limited to 100 elements for performance reasons */
|
||||||
static int findconst(bfuncinfo *finfo, bexpdesc *e)
|
static int findconst(bfuncinfo *finfo, bexpdesc *e)
|
||||||
{
|
{
|
||||||
int i, count = be_vector_count(&finfo->kvec);
|
int i, count = be_vector_count(&finfo->kvec);
|
||||||
|
@ -260,7 +260,7 @@ static int findconst(bfuncinfo *finfo, bexpdesc *e)
|
||||||
* so only search the constant table for the
|
* so only search the constant table for the
|
||||||
* previous value.
|
* previous value.
|
||||||
**/
|
**/
|
||||||
count = count < 50 ? count : 50;
|
count = count < 100 ? count : 100;
|
||||||
for (i = 0; i < count; ++i) {
|
for (i = 0; i < count; ++i) {
|
||||||
bvalue *k = be_vector_at(&finfo->kvec, i);
|
bvalue *k = be_vector_at(&finfo->kvec, i);
|
||||||
switch (e->type) {
|
switch (e->type) {
|
||||||
|
@ -746,10 +746,12 @@ int be_code_proto(bfuncinfo *finfo, bproto *proto)
|
||||||
|
|
||||||
void be_code_closure(bfuncinfo *finfo, bexpdesc *e, int idx)
|
void be_code_closure(bfuncinfo *finfo, bexpdesc *e, int idx)
|
||||||
{
|
{
|
||||||
int reg = e->type == ETGLOBAL ? finfo->freereg: e->v.idx;
|
int reg = (e->type == ETGLOBAL || e->type == ETNGLOBAL) ? finfo->freereg: e->v.idx;
|
||||||
code_closure(finfo, idx, reg);
|
code_closure(finfo, idx, reg);
|
||||||
if (e->type == ETGLOBAL) { /* store to grobal R(A) -> G(Bx) */
|
if (e->type == ETGLOBAL) { /* store to global R(A) -> G(Bx) */
|
||||||
codeABx(finfo, OP_SETGBL, reg, e->v.idx);
|
codeABx(finfo, OP_SETGBL, reg, e->v.idx);
|
||||||
|
} else if (e->type == ETNGLOBAL) { /* store R(A) -> GLOBAL[RK(B)] */
|
||||||
|
codeABC(finfo, OP_SETNGBL, reg, e->v.idx, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -841,9 +843,12 @@ void be_code_class(bfuncinfo *finfo, bexpdesc *dst, bclass *c)
|
||||||
src = newconst(finfo, &var); /* allocate a new constant and return kreg */
|
src = newconst(finfo, &var); /* allocate a new constant and return kreg */
|
||||||
if (dst->type == ETLOCAL) { /* if target is a local variable, just assign */
|
if (dst->type == ETLOCAL) { /* if target is a local variable, just assign */
|
||||||
codeABx(finfo, OP_LDCONST, dst->v.idx, src);
|
codeABx(finfo, OP_LDCONST, dst->v.idx, src);
|
||||||
} else { /* otherwise set as global with same name as class name */
|
} else if (dst->type == ETGLOBAL) { /* otherwise set as global with same name as class name */
|
||||||
codeABx(finfo, OP_LDCONST, finfo->freereg, src);
|
codeABx(finfo, OP_LDCONST, finfo->freereg, src);
|
||||||
codeABx(finfo, OP_SETGBL, finfo->freereg, dst->v.idx);
|
codeABx(finfo, OP_SETGBL, finfo->freereg, dst->v.idx);
|
||||||
|
} else if (dst->type == ETNGLOBAL) {
|
||||||
|
codeABx(finfo, OP_LDCONST, finfo->freereg, src);
|
||||||
|
codeABC(finfo, OP_SETNGBL, finfo->freereg, dst->v.idx, 0);
|
||||||
}
|
}
|
||||||
codeABx(finfo, OP_CLASS, 0, src); /* emit CLASS opcode to register class */
|
codeABx(finfo, OP_CLASS, 0, src); /* emit CLASS opcode to register class */
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ void be_print_inst(binstruction ins, int pc)
|
||||||
case OP_OR: case OP_XOR: case OP_SHL: case OP_SHR:
|
case OP_OR: case OP_XOR: case OP_SHL: case OP_SHR:
|
||||||
logbuf("%s\tR%d\t%c%d\t%c%d", opc2str(op), IGET_RA(ins),
|
logbuf("%s\tR%d\t%c%d\t%c%d", opc2str(op), IGET_RA(ins),
|
||||||
isKB(ins) ? 'K' : 'R', IGET_RKB(ins) & KR_MASK,
|
isKB(ins) ? 'K' : 'R', IGET_RKB(ins) & KR_MASK,
|
||||||
isKB(ins) ? 'K' : 'R', IGET_RKC(ins) & KR_MASK);
|
isKC(ins) ? 'K' : 'R', IGET_RKC(ins) & KR_MASK);
|
||||||
break;
|
break;
|
||||||
case OP_GETNGBL: case OP_SETNGBL:
|
case OP_GETNGBL: case OP_SETNGBL:
|
||||||
logbuf("%s\tR%d\t%c%d", opc2str(op), IGET_RA(ins),
|
logbuf("%s\tR%d\t%c%d", opc2str(op), IGET_RA(ins),
|
||||||
|
@ -116,7 +116,7 @@ void be_print_inst(binstruction ins, int pc)
|
||||||
case OP_RAISE:
|
case OP_RAISE:
|
||||||
logbuf("%s\t%d\t%c%d\t%c%d", opc2str(op), IGET_RA(ins),
|
logbuf("%s\t%d\t%c%d\t%c%d", opc2str(op), IGET_RA(ins),
|
||||||
isKB(ins) ? 'K' : 'R', IGET_RKB(ins) & KR_MASK,
|
isKB(ins) ? 'K' : 'R', IGET_RKB(ins) & KR_MASK,
|
||||||
isKB(ins) ? 'K' : 'R', IGET_RKC(ins) & KR_MASK);
|
isKC(ins) ? 'K' : 'R', IGET_RKC(ins) & KR_MASK);
|
||||||
break;
|
break;
|
||||||
case OP_EXBLK:
|
case OP_EXBLK:
|
||||||
if (IGET_RA(ins)) {
|
if (IGET_RA(ins)) {
|
||||||
|
|
|
@ -299,22 +299,58 @@ void be_module_delete(bvm *vm, bmodule *module)
|
||||||
be_free(vm, module, sizeof(bmodule));
|
be_free(vm, module, sizeof(bmodule));
|
||||||
}
|
}
|
||||||
|
|
||||||
bvalue* be_module_attr(bvm *vm, bmodule *module, bstring *attr)
|
int be_module_attr(bvm *vm, bmodule *module, bstring *attr, bvalue *dst)
|
||||||
{
|
{
|
||||||
return be_map_findstr(vm, module->table, attr);
|
bvalue *member = be_map_findstr(vm, module->table, attr);
|
||||||
|
if (!member) { /* try the 'member' function */
|
||||||
|
member = be_map_findstr(vm, module->table, str_literal(vm, "member"));
|
||||||
|
if (member && var_basetype(member) == BE_FUNCTION) {
|
||||||
|
bvalue *top = vm->top;
|
||||||
|
top[0] = *member;
|
||||||
|
var_setstr(&top[1], attr);
|
||||||
|
vm->top += 2; /* prevent collection results */
|
||||||
|
be_dofunc(vm, top, 1); /* call method 'method' */
|
||||||
|
vm->top -= 2;
|
||||||
|
*dst = *vm->top; /* copy result to R(A) */
|
||||||
|
if (var_basetype(dst) != BE_NIL) {
|
||||||
|
return var_type(dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BE_NONE;
|
||||||
|
} else {
|
||||||
|
*dst = *member;
|
||||||
|
return var_type(dst);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bvalue* be_module_bind(bvm *vm, bmodule *module, bstring *attr)
|
bbool be_module_setmember(bvm *vm, bmodule *module, bstring *attr, bvalue *src)
|
||||||
{
|
{
|
||||||
|
assert(src);
|
||||||
bmap *attrs = module->table;
|
bmap *attrs = module->table;
|
||||||
if (!gc_isconst(attrs)) {
|
if (!gc_isconst(attrs)) {
|
||||||
bvalue *v = be_map_findstr(vm, attrs, attr);
|
bvalue *v = be_map_findstr(vm, attrs, attr);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
v = be_map_insertstr(vm, attrs, attr, NULL);
|
v = be_map_insertstr(vm, attrs, attr, NULL);
|
||||||
}
|
}
|
||||||
return v;
|
if (v) {
|
||||||
|
*v = *src;
|
||||||
|
return btrue;
|
||||||
}
|
}
|
||||||
return NULL;
|
} else {
|
||||||
|
/* if not writable, try 'setmember' */
|
||||||
|
int type = be_module_attr(vm, module, str_literal(vm, "setmember"), vm->top);
|
||||||
|
if (type == BE_FUNCTION) {
|
||||||
|
bvalue *top = vm->top;
|
||||||
|
// top[0] already has 'member'
|
||||||
|
var_setstr(&top[1], attr); /* attribute name */
|
||||||
|
top[2] = *src; /* new value */
|
||||||
|
vm->top += 3; /* prevent collection results */
|
||||||
|
be_dofunc(vm, top, 2); /* call method 'setmember' */
|
||||||
|
vm->top -= 3;
|
||||||
|
return btrue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* be_module_name(bmodule *module)
|
const char* be_module_name(bmodule *module)
|
||||||
|
|
|
@ -34,8 +34,8 @@ typedef struct bmodule {
|
||||||
bmodule* be_module_new(bvm *vm);
|
bmodule* be_module_new(bvm *vm);
|
||||||
void be_module_delete(bvm *vm, bmodule *module);
|
void be_module_delete(bvm *vm, bmodule *module);
|
||||||
int be_module_load(bvm *vm, bstring *path);
|
int be_module_load(bvm *vm, bstring *path);
|
||||||
bvalue* be_module_attr(bvm *vm, bmodule *module, bstring *attr);
|
int be_module_attr(bvm *vm, bmodule *module, bstring *attr, bvalue *dst);
|
||||||
bvalue* be_module_bind(bvm *vm, bmodule *module, bstring *attr);
|
bbool be_module_setmember(bvm *vm, bmodule *module, bstring *attr, bvalue *src);
|
||||||
const char* be_module_name(bmodule *module);
|
const char* be_module_name(bmodule *module);
|
||||||
bbool be_module_setname(bmodule *module, bstring *name);
|
bbool be_module_setname(bmodule *module, bstring *name);
|
||||||
|
|
||||||
|
|
|
@ -461,6 +461,14 @@ static void new_var(bparser *parser, bstring *name, bexpdesc *var)
|
||||||
push_error(parser,
|
push_error(parser,
|
||||||
"too many global variables (in '%s')", str(name));
|
"too many global variables (in '%s')", str(name));
|
||||||
}
|
}
|
||||||
|
if (comp_is_named_gbl(parser->vm)) {
|
||||||
|
/* change to ETNGLBAL */
|
||||||
|
bexpdesc key;
|
||||||
|
init_exp(&key, ETSTRING, 0);
|
||||||
|
key.v.s = name;
|
||||||
|
init_exp(var, ETNGLOBAL, 0);
|
||||||
|
var->v.idx = be_code_nglobal(parser->finfo, &key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,6 @@ int be_eqstr(bstring *s1, bstring *s2)
|
||||||
blstring *ls2 = cast(blstring*, s2);
|
blstring *ls2 = cast(blstring*, s2);
|
||||||
return ls1->llen == ls2->llen && !strcmp(lstr(ls1), lstr(ls2));
|
return ls1->llen == ls2->llen && !strcmp(lstr(ls1), lstr(ls2));
|
||||||
}
|
}
|
||||||
// TODO one is long const and the other is long string
|
|
||||||
/* const short strings */
|
/* const short strings */
|
||||||
if (gc_isconst(s1) || gc_isconst(s2)) { /* one of the two string is short const */
|
if (gc_isconst(s1) || gc_isconst(s2)) { /* one of the two string is short const */
|
||||||
if (cast(bcstring*, s1)->hash && cast(bcstring*, s2)->hash) {
|
if (cast(bcstring*, s1)->hash && cast(bcstring*, s2)->hash) {
|
||||||
|
|
|
@ -275,26 +275,10 @@ static void obj_method(bvm *vm, bvalue *o, bstring *attr, bvalue *dst)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int obj_attribute(bvm *vm, bvalue *o, bvalue *c, bvalue *dst)
|
static int obj_attribute(bvm *vm, bvalue *o, bstring *attr, bvalue *dst)
|
||||||
{
|
{
|
||||||
bvalue instance = *o; /* save instance to send it later to member */
|
|
||||||
bstring *attr = var_tostr(c);
|
|
||||||
binstance *obj = var_toobj(o);
|
binstance *obj = var_toobj(o);
|
||||||
int type = be_instance_member(vm, obj, attr, dst);
|
int type = be_instance_member(vm, obj, attr, dst);
|
||||||
if (type == BE_NONE) { /* if no method found, try virtual */
|
|
||||||
/* get method 'member' */
|
|
||||||
int type2 = be_instance_member(vm, obj, str_literal(vm, "member"), vm->top);
|
|
||||||
if (basetype(type2) == BE_FUNCTION) {
|
|
||||||
bvalue *top = vm->top;
|
|
||||||
top[1] = instance; /* move instance to argv[0] */
|
|
||||||
top[2] = *c; /* move method name to argv[1] */
|
|
||||||
vm->top += 3; /* prevent collection results */
|
|
||||||
be_dofunc(vm, top, 2); /* call method 'member' */
|
|
||||||
vm->top -= 3;
|
|
||||||
*dst = *vm->top; /* copy result to R(A) */
|
|
||||||
type = var_type(dst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (type == BE_NONE) {
|
if (type == BE_NONE) {
|
||||||
vm_error(vm, "attribute_error",
|
vm_error(vm, "attribute_error",
|
||||||
"the '%s' object has no attribute '%s'",
|
"the '%s' object has no attribute '%s'",
|
||||||
|
@ -316,6 +300,19 @@ static int class_attribute(bvm *vm, bvalue *o, bvalue *c, bvalue *dst)
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int module_attribute(bvm *vm, bvalue *o, bvalue *c, bvalue *dst)
|
||||||
|
{
|
||||||
|
bstring *attr = var_tostr(c);
|
||||||
|
bmodule *module = var_toobj(o);
|
||||||
|
int type = be_module_attr(vm, module, attr, dst);
|
||||||
|
if (type == BE_NONE) {
|
||||||
|
vm_error(vm, "attribute_error",
|
||||||
|
"module '%s' has no member '%s'",
|
||||||
|
be_module_name(module), str(attr));
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
static bbool object_eqop(bvm *vm,
|
static bbool object_eqop(bvm *vm,
|
||||||
const char *op, bbool iseq, bvalue *a, bvalue *b)
|
const char *op, bbool iseq, bvalue *a, bvalue *b)
|
||||||
{
|
{
|
||||||
|
@ -529,12 +526,8 @@ newframe: /* a new call frame */
|
||||||
bvalue *b = RKB();
|
bvalue *b = RKB();
|
||||||
if (var_isstr(b)) {
|
if (var_isstr(b)) {
|
||||||
bstring *name = var_tostr(b);
|
bstring *name = var_tostr(b);
|
||||||
int idx = be_global_find(vm, name);
|
int idx = be_global_new(vm, name);
|
||||||
if (idx > -1) {
|
|
||||||
*be_global_var(vm, idx) = *v;
|
*be_global_var(vm, idx) = *v;
|
||||||
} else {
|
|
||||||
vm_error(vm, "attribute_error", "'%s' undeclared", str(name));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
vm_error(vm, "internal_error", "global name must be a string");
|
vm_error(vm, "internal_error", "global name must be a string");
|
||||||
}
|
}
|
||||||
|
@ -793,35 +786,14 @@ newframe: /* a new call frame */
|
||||||
opcase(GETMBR): {
|
opcase(GETMBR): {
|
||||||
bvalue *a = RA(), *b = RKB(), *c = RKC();
|
bvalue *a = RA(), *b = RKB(), *c = RKC();
|
||||||
if (var_isinstance(b) && var_isstr(c)) {
|
if (var_isinstance(b) && var_isstr(c)) {
|
||||||
obj_attribute(vm, b, c, a);
|
obj_attribute(vm, b, var_tostr(c), a);
|
||||||
reg = vm->reg;
|
reg = vm->reg;
|
||||||
} else if (var_isclass(b) && var_isstr(c)) {
|
} else if (var_isclass(b) && var_isstr(c)) {
|
||||||
class_attribute(vm, b, c, a);
|
class_attribute(vm, b, c, a);
|
||||||
reg = vm->reg;
|
reg = vm->reg;
|
||||||
} else if (var_ismodule(b) && var_isstr(c)) {
|
} else if (var_ismodule(b) && var_isstr(c)) {
|
||||||
bstring *attr = var_tostr(c);
|
module_attribute(vm, b, c, a);
|
||||||
bmodule *module = var_toobj(b);
|
reg = vm->reg;
|
||||||
bvalue *v = be_module_attr(vm, module, attr);
|
|
||||||
if (v) {
|
|
||||||
*a = *v;
|
|
||||||
} else {
|
|
||||||
bvalue *member = be_module_attr(vm, module, str_literal(vm, "member"));
|
|
||||||
var_setnil(a);
|
|
||||||
if (member && var_basetype(member) == BE_FUNCTION) {
|
|
||||||
bvalue *top = vm->top;
|
|
||||||
top[0] = *member;
|
|
||||||
top[1] = *c; /* move name to argv[0] */
|
|
||||||
vm->top += 2; /* prevent collection results */
|
|
||||||
be_dofunc(vm, top, 1); /* call method 'method' */
|
|
||||||
vm->top -= 2;
|
|
||||||
*a = *vm->top; /* copy result to R(A) */
|
|
||||||
}
|
|
||||||
if (var_basetype(a) == BE_NIL) {
|
|
||||||
vm_error(vm, "attribute_error",
|
|
||||||
"module '%s' has no attribute '%s'",
|
|
||||||
be_module_name(module), str(attr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
attribute_error(vm, "attribute", b, c);
|
attribute_error(vm, "attribute", b, c);
|
||||||
}
|
}
|
||||||
|
@ -830,49 +802,23 @@ newframe: /* a new call frame */
|
||||||
opcase(GETMET): {
|
opcase(GETMET): {
|
||||||
bvalue *a = RA(), *b = RKB(), *c = RKC();
|
bvalue *a = RA(), *b = RKB(), *c = RKC();
|
||||||
if (var_isinstance(b) && var_isstr(c)) {
|
if (var_isinstance(b) && var_isstr(c)) {
|
||||||
bvalue self = *b;
|
|
||||||
bstring *attr = var_tostr(c);
|
|
||||||
binstance *obj = var_toobj(b);
|
binstance *obj = var_toobj(b);
|
||||||
int type = obj_attribute(vm, b, c, a);
|
int type = obj_attribute(vm, b, var_tostr(c), a);
|
||||||
reg = vm->reg;
|
reg = vm->reg;
|
||||||
if (basetype(type) == BE_FUNCTION) {
|
if (basetype(type) == BE_FUNCTION) {
|
||||||
/* check if the object is a superinstance, if so get the lowest possible subclass */
|
/* check if the object is a superinstance, if so get the lowest possible subclass */
|
||||||
while (obj->sub) {
|
while (obj->sub) {
|
||||||
obj = obj->sub;
|
obj = obj->sub;
|
||||||
}
|
}
|
||||||
var_setobj(&self, var_type(&self), obj); /* replace superinstance by lowest subinstance */
|
var_setinstance(&a[1], obj); /* replace superinstance by lowest subinstance */
|
||||||
a[1] = self;
|
|
||||||
} else {
|
} else {
|
||||||
vm_error(vm, "attribute_error",
|
vm_error(vm, "attribute_error",
|
||||||
"class '%s' has no method '%s'",
|
"class '%s' has no method '%s'",
|
||||||
str(be_instance_name(obj)), str(attr));
|
str(be_instance_name(obj)), str(var_tostr(c)));
|
||||||
}
|
}
|
||||||
} else if (var_ismodule(b) && var_isstr(c)) {
|
} else if (var_ismodule(b) && var_isstr(c)) {
|
||||||
bstring *attr = var_tostr(c);
|
module_attribute(vm, b, c, &a[1]);
|
||||||
bmodule *module = var_toobj(b);
|
|
||||||
bvalue *src = be_module_attr(vm, module, attr);
|
|
||||||
if (src) {
|
|
||||||
var_settype(a, NOT_METHOD);
|
var_settype(a, NOT_METHOD);
|
||||||
a[1] = *src;
|
|
||||||
} else {
|
|
||||||
bvalue *member = be_module_attr(vm, module, str_literal(vm, "member"));
|
|
||||||
var_setnil(a);
|
|
||||||
if (member && var_basetype(member) == BE_FUNCTION) {
|
|
||||||
bvalue *top = vm->top;
|
|
||||||
top[0] = *member;
|
|
||||||
top[1] = *c; /* move name to argv[0] */
|
|
||||||
vm->top += 2; /* prevent collection results */
|
|
||||||
be_dofunc(vm, top, 1); /* call method 'method' */
|
|
||||||
vm->top -= 2;
|
|
||||||
var_settype(a, NOT_METHOD);
|
|
||||||
a[1] = *vm->top; /* copy result to R(A) */
|
|
||||||
}
|
|
||||||
if (var_basetype(a) == BE_NIL) {
|
|
||||||
vm_error(vm, "attribute_error",
|
|
||||||
"module '%s' has no method '%s'",
|
|
||||||
be_module_name(module), str(attr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
attribute_error(vm, "method", b, c);
|
attribute_error(vm, "method", b, c);
|
||||||
}
|
}
|
||||||
|
@ -903,23 +849,10 @@ newframe: /* a new call frame */
|
||||||
if (var_ismodule(a) && var_isstr(b)) {
|
if (var_ismodule(a) && var_isstr(b)) {
|
||||||
bmodule *obj = var_toobj(a);
|
bmodule *obj = var_toobj(a);
|
||||||
bstring *attr = var_tostr(b);
|
bstring *attr = var_tostr(b);
|
||||||
bvalue tmp = *c; /* stack may change */
|
if (be_module_setmember(vm, obj, attr, c)) {
|
||||||
bvalue *v = be_module_bind(vm, obj, attr);
|
|
||||||
if (v != NULL) {
|
|
||||||
*v = tmp;
|
|
||||||
dispatch();
|
|
||||||
}
|
|
||||||
/* if it failed, try 'setmeemner' */
|
|
||||||
bvalue *member = be_module_attr(vm, obj, str_literal(vm, "setmember"));
|
|
||||||
if (member && var_basetype(member) == BE_FUNCTION) {
|
|
||||||
bvalue *top = vm->top;
|
|
||||||
top[0] = *member;
|
|
||||||
top[1] = *b; /* move name to argv[0] */
|
|
||||||
top[2] = tmp; /* move value to argv[1] */
|
|
||||||
vm->top += 3; /* prevent collection results */
|
|
||||||
be_dofunc(vm, top, 2); /* call method 'setmember' */
|
|
||||||
vm->top -= 3;
|
|
||||||
dispatch();
|
dispatch();
|
||||||
|
} else {
|
||||||
|
// fall through exception below
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
attribute_error(vm, "writable attribute", a, b);
|
attribute_error(vm, "writable attribute", a, b);
|
||||||
|
@ -1118,14 +1051,10 @@ newframe: /* a new call frame */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BE_MODULE: {
|
case BE_MODULE: {
|
||||||
bmodule *f = var_toobj(var);
|
bvalue attr;
|
||||||
bvalue *member = be_module_attr(vm, f, str_literal(vm, "()"));
|
var_setstr(&attr, str_literal(vm, "()"));
|
||||||
if (member && var_basetype(member) == BE_FUNCTION) {
|
module_attribute(vm, var, &attr, var); /* exception if not found */
|
||||||
*var = *member;
|
|
||||||
goto recall; /* call '()' method */
|
goto recall; /* call '()' method */
|
||||||
} else {
|
|
||||||
call_error(vm, var);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -4,18 +4,13 @@
|
||||||
-- description
|
-- description
|
||||||
--
|
--
|
||||||
-- a double dash ('--') start a line comment.
|
-- a double dash ('--') start a line comment.
|
||||||
-- a: n means that the size of entity 'a' is 'n' bytes.
|
-- a: b means that the entity 'a' is realized by the 'b' structure.
|
||||||
-- 'a: .n means that the size of entity 'a' is 'n' bits.
|
-- a: b c 'b' and 'c' are arranged in a compact order (one byte alignment).
|
||||||
-- a:
|
|
||||||
-- b means that the entity 'a' is realized by the 'b' structure.
|
|
||||||
-- a:
|
|
||||||
-- b
|
|
||||||
-- c 'b' and 'c' are arranged in a compact order (one byte alignment).
|
|
||||||
-- [a] means that structure 'a' can be repeated 0 to any times.
|
-- [a] means that structure 'a' can be repeated 0 to any times.
|
||||||
-- [a](b) means that structure 'a' can be repeated 'b' times.
|
-- [a](b) means that structure 'a' can be repeated 'b' times.
|
||||||
-- a | b means that the entity can be implemented by structure 'a' or 'b'.
|
-- a | b means that the entity can be implemented by structure 'a' or 'b'.
|
||||||
-- a -> b is equivalent to 'a:
|
-- N a number indicates the byte count of the field (eg. 'a: 1').
|
||||||
-- b'.
|
-- .N means the number of bits in the field (eg. 'a: .1').
|
||||||
-- only the first entity is a file entity (the root).
|
-- only the first entity is a file entity (the root).
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -26,7 +21,7 @@ bytecode_file: -- little endian
|
||||||
|
|
||||||
header: 8
|
header: 8
|
||||||
magic_number: 3 -- 0xbecdfe (berry code file)
|
magic_number: 3 -- 0xbecdfe (berry code file)
|
||||||
version: 1 -- update with file structure definition
|
version: 2 -- update with file structure definition
|
||||||
integer_size: .1
|
integer_size: .1
|
||||||
float_size: .1
|
float_size: .1
|
||||||
-- reserved space
|
-- reserved space
|
||||||
|
@ -35,7 +30,7 @@ main_function -> function
|
||||||
|
|
||||||
global_desc:
|
global_desc:
|
||||||
builtin_count: 4
|
builtin_count: 4
|
||||||
global_count: 4
|
global_count: 4 -- excluding builtins
|
||||||
global_name -> [
|
global_name -> [
|
||||||
string
|
string
|
||||||
](global_count)
|
](global_count)
|
||||||
|
@ -48,7 +43,8 @@ function:
|
||||||
string
|
string
|
||||||
argc: 1 -- arguments count
|
argc: 1 -- arguments count
|
||||||
nstack: 1 -- number of stack size by this function
|
nstack: 1 -- number of stack size by this function
|
||||||
extra: 2 -- extra data
|
varg: 1
|
||||||
|
extra: 1 -- extra data
|
||||||
bytecode:
|
bytecode:
|
||||||
code_size: 4
|
code_size: 4
|
||||||
code_array -> [ -- bytecode array
|
code_array -> [ -- bytecode array
|
||||||
|
@ -62,7 +58,7 @@ function:
|
||||||
[function](proto_count)
|
[function](proto_count)
|
||||||
upval_table:
|
upval_table:
|
||||||
upval_count: 1
|
upval_count: 1
|
||||||
upvals -> [
|
upvals: [
|
||||||
instack: 1
|
instack: 1
|
||||||
index: 1
|
index: 1
|
||||||
](upval_count)
|
](upval_count)
|
||||||
|
@ -82,7 +78,7 @@ class:
|
||||||
string
|
string
|
||||||
member_count: 4 -- number of member variables
|
member_count: 4 -- number of member variables
|
||||||
method_count: 4 -- number of method
|
method_count: 4 -- number of method
|
||||||
method_table -> [
|
method_table: [
|
||||||
string -- method name
|
string -- method name
|
||||||
function -- method function body
|
function -- method function body
|
||||||
](method_count)
|
](method_count)
|
||||||
|
@ -92,5 +88,5 @@ class:
|
||||||
|
|
||||||
nil: 1
|
nil: 1
|
||||||
boolean: 1
|
boolean: 1
|
||||||
integer: 4 or 8
|
integer: 4 | 8
|
||||||
float: 4 or 8
|
float: 4 | 8
|
||||||
|
|
|
@ -809,13 +809,11 @@ extern "C" {
|
||||||
|
|
||||||
// all good
|
// all good
|
||||||
be_return(vm);
|
be_return(vm);
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
be_return_nil(vm);
|
be_return_nil(vm);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
be_raise(vm, "attribute_error", "module 'lvgl' has no such attribute");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* LVGL Start
|
* LVGL Start
|
||||||
|
|
|
@ -57,9 +57,12 @@ extern "C" {
|
||||||
// we did have a match, low == high
|
// we did have a match, low == high
|
||||||
be_pushint(vm, webserver_constants[constant_idx].value);
|
be_pushint(vm, webserver_constants[constant_idx].value);
|
||||||
be_return(vm);
|
be_return(vm);
|
||||||
|
} else if (strcmp(needle, "init")) {
|
||||||
|
/* don't throw an exception if the 'init' function is requested */
|
||||||
|
be_raise(vm, "attribute_error", be_pushfstring(vm, "module 'webserver' has no such attribute '%s'", needle));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
be_raise(vm, "attribute_error", "module 'webserver' has no such attribute");
|
be_return_nil(vm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue