Berry upgrade to latest changes

This commit is contained in:
Stephan Hadinger 2021-08-24 22:44:33 +02:00
parent 228593c092
commit 5ab0081f47
13 changed files with 197 additions and 187 deletions

View File

@ -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)
{
int res = BE_NIL;
bvalue *o = be_indexof(vm, index);
bvalue *v = be_indexof(vm, -1);
if (var_isinstance(o)) {
bstring *key = be_newstr(vm, k);
bvalue *v = be_indexof(vm, -1);
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)) {
bstring *key = be_newstr(vm, k);
bmodule *mod = var_toobj(o);
bvalue *v = be_module_bind(vm, mod, key);
if (v) {
*v = *be_indexof(vm, -1);
return btrue;
}
return be_module_setmember(vm, mod, key, v);
}
return res != BE_NIL;
return bfalse;
}
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)) {
binstance *obj = var_toobj(o);
type = be_instance_member(vm, obj, be_newstr(vm, k), top);
if (type == BE_NONE) {
type = BE_NIL;
}
} else if (var_isclass(o) && !onlyins) {
bclass *cl = var_toobj(o);
type = be_class_member(vm, cl, be_newstr(vm, k), top);
} else if (var_ismodule(o) && !onlyins) {
bmodule *module = var_toobj(o);
bvalue *v = be_module_attr(vm, module, be_newstr(vm, k));
if (v != NULL) {
*top = *v;
type = v->type;
}
type = be_module_attr(vm, module, be_newstr(vm, k), top);
}
if (type == BE_NONE) {
type = BE_NIL;
}
return type;
}

View File

@ -23,7 +23,7 @@
#define MAGIC_NUMBER1 0xBE
#define MAGIC_NUMBER2 0xCD
#define MAGIC_NUMBER3 0xFE
#define BYTECODE_VERSION 1
#define BYTECODE_VERSION 2
#define USE_64BIT_INT (BE_INTGER_TYPE == 2 \
|| 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;
save_long(fp, (uint32_t)proto->codesize);
for (end = code + proto->codesize; code < end; ++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_byte(fp, proto->argc); /* argc */
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_proto_table(vm, fp, proto); /* proto 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)
{
save_long(fp, be_builtin_count(vm));
save_long(fp, be_global_count(vm));
save_globals(vm, fp);
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_globals(vm, fp);
}
}
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 */
#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)
{
@ -313,9 +326,13 @@ static int load_head(void *fp)
res = buffer[0] == MAGIC_NUMBER1 &&
buffer[1] == MAGIC_NUMBER2 &&
buffer[2] == MAGIC_NUMBER3 &&
buffer[3] == BYTECODE_VERSION &&
buffer[3] <= BYTECODE_VERSION &&
buffer[4] == vm_sizeinfo();
return res;
if (res) {
return buffer[3];
} else {
return 0;
}
}
bbool be_bytecode_check(const char *path)
@ -385,7 +402,7 @@ static bstring* cache_string(bvm *vm, void *fp)
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;
bclass *c = be_newclass(vm, NULL, NULL);
@ -399,7 +416,7 @@ static void load_class(bvm *vm, void *fp, bvalue *v)
value = vm->top;
var_setproto(value, NULL);
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_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)) {
case BE_INT: var_setint(v, load_int(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_CLASS: load_class(vm, fp, v); break;
case BE_CLASS: load_class(vm, fp, v, version); 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 */
if (size) {
@ -458,12 +475,12 @@ static void load_constant(bvm *vm, void *fp, bproto *proto)
proto->ktab = v;
proto->nconst = size;
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 */
if (size) {
@ -472,7 +489,7 @@ static void load_proto_table(bvm *vm, void *fp, bproto *proto)
proto->ptab = p;
proto->nproto = 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)->name = load_string(vm, fp);
(*proto)->source = load_string(vm, fp);
(*proto)->argc = 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_constant(vm, fp, *proto);
load_proto_table(vm, fp, *proto);
load_constant(vm, fp, *proto, version);
load_proto_table(vm, fp, *proto, version);
load_upvals(vm, fp, *proto);
}
@ -510,7 +531,7 @@ void load_global_info(bvm *vm, void *fp)
int i;
int bcnt = (int)load_long(fp); /* builtin 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,
"inconsistent number of builtin objects."));
}
@ -530,15 +551,18 @@ bclosure* be_bytecode_load(bvm *vm, const char *filename)
if (fp == NULL) {
bytecode_error(vm, be_pushfstring(vm,
"can not open file '%s'.", filename));
} else if (load_head(fp)) {
bclosure *cl = be_newclosure(vm, 0);
var_setclosure(vm->top, cl);
be_stackpush(vm);
load_global_info(vm, fp);
load_proto(vm, fp, &cl->proto, -1);
be_stackpop(vm, 2); /* pop the closure and list */
be_fclose(fp);
return cl;
} else {
int version = load_head(fp);
if (version) {
bclosure *cl = be_newclosure(vm, 0);
var_setclosure(vm->top, cl);
be_stackpush(vm);
load_global_info(vm, fp);
load_proto(vm, fp, &cl->proto, -1, version);
be_stackpop(vm, 2); /* pop the closure and list */
be_fclose(fp);
return cl;
}
}
bytecode_error(vm, be_pushfstring(vm,
"invalid bytecode file '%s'.", filename));

View File

@ -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 */
/* Returns the type of the member or BE_NONE if member not found */
/* 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;
be_assert(name != NULL);
obj = instance_member(vm, obj, name, dst);
binstance * obj = instance_member(vm, instance, name, dst);
type = var_type(dst);
if (obj && type == MT_VARIABLE) {
*dst = obj->members[dst->v.i];
}
if (obj) {
return type;
} else {
return BE_NONE;
} else { /* if no method found, try virtual */
/* 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)

View File

@ -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 */
/* 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)
{
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
* previous value.
**/
count = count < 50 ? count : 50;
count = count < 100 ? count : 100;
for (i = 0; i < count; ++i) {
bvalue *k = be_vector_at(&finfo->kvec, i);
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)
{
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);
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);
} 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 */
if (dst->type == ETLOCAL) { /* if target is a local variable, just assign */
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_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 */
}

View File

@ -62,7 +62,7 @@ void be_print_inst(binstruction ins, int pc)
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),
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;
case OP_GETNGBL: case OP_SETNGBL:
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:
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_RKC(ins) & KR_MASK);
isKC(ins) ? 'K' : 'R', IGET_RKC(ins) & KR_MASK);
break;
case OP_EXBLK:
if (IGET_RA(ins)) {

View File

@ -299,22 +299,58 @@ void be_module_delete(bvm *vm, bmodule *module)
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;
if (!gc_isconst(attrs)) {
bvalue *v = be_map_findstr(vm, attrs, attr);
if (v == NULL) {
v = be_map_insertstr(vm, attrs, attr, NULL);
}
return v;
if (v) {
*v = *src;
return btrue;
}
} 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 NULL;
return bfalse;
}
const char* be_module_name(bmodule *module)

View File

@ -34,8 +34,8 @@ typedef struct bmodule {
bmodule* be_module_new(bvm *vm);
void be_module_delete(bvm *vm, bmodule *module);
int be_module_load(bvm *vm, bstring *path);
bvalue* be_module_attr(bvm *vm, bmodule *module, bstring *attr);
bvalue* be_module_bind(bvm *vm, bmodule *module, bstring *attr);
int be_module_attr(bvm *vm, bmodule *module, bstring *attr, bvalue *dst);
bbool be_module_setmember(bvm *vm, bmodule *module, bstring *attr, bvalue *src);
const char* be_module_name(bmodule *module);
bbool be_module_setname(bmodule *module, bstring *name);

View File

@ -461,6 +461,14 @@ static void new_var(bparser *parser, bstring *name, bexpdesc *var)
push_error(parser,
"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);
}
}
}

View File

@ -55,7 +55,6 @@ int be_eqstr(bstring *s1, bstring *s2)
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) {

View File

@ -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);
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) {
vm_error(vm, "attribute_error",
"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;
}
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,
const char *op, bbool iseq, bvalue *a, bvalue *b)
{
@ -529,12 +526,8 @@ newframe: /* a new call frame */
bvalue *b = RKB();
if (var_isstr(b)) {
bstring *name = var_tostr(b);
int idx = be_global_find(vm, name);
if (idx > -1) {
*be_global_var(vm, idx) = *v;
} else {
vm_error(vm, "attribute_error", "'%s' undeclared", str(name));
}
int idx = be_global_new(vm, name);
*be_global_var(vm, idx) = *v;
} else {
vm_error(vm, "internal_error", "global name must be a string");
}
@ -793,35 +786,14 @@ newframe: /* a new call frame */
opcase(GETMBR): {
bvalue *a = RA(), *b = RKB(), *c = RKC();
if (var_isinstance(b) && var_isstr(c)) {
obj_attribute(vm, b, c, a);
obj_attribute(vm, b, var_tostr(c), a);
reg = vm->reg;
} else if (var_isclass(b) && var_isstr(c)) {
class_attribute(vm, b, c, a);
reg = vm->reg;
} else if (var_ismodule(b) && var_isstr(c)) {
bstring *attr = var_tostr(c);
bmodule *module = var_toobj(b);
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));
}
}
module_attribute(vm, b, c, a);
reg = vm->reg;
} else {
attribute_error(vm, "attribute", b, c);
}
@ -830,49 +802,23 @@ newframe: /* a new call frame */
opcase(GETMET): {
bvalue *a = RA(), *b = RKB(), *c = RKC();
if (var_isinstance(b) && var_isstr(c)) {
bvalue self = *b;
bstring *attr = var_tostr(c);
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;
if (basetype(type) == BE_FUNCTION) {
/* check if the object is a superinstance, if so get the lowest possible subclass */
while (obj->sub) {
obj = obj->sub;
}
var_setobj(&self, var_type(&self), obj); /* replace superinstance by lowest subinstance */
a[1] = self;
var_setinstance(&a[1], obj); /* replace superinstance by lowest subinstance */
} else {
vm_error(vm, "attribute_error",
"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)) {
bstring *attr = var_tostr(c);
bmodule *module = var_toobj(b);
bvalue *src = be_module_attr(vm, module, attr);
if (src) {
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));
}
}
module_attribute(vm, b, c, &a[1]);
var_settype(a, NOT_METHOD);
} else {
attribute_error(vm, "method", b, c);
}
@ -903,23 +849,10 @@ newframe: /* a new call frame */
if (var_ismodule(a) && var_isstr(b)) {
bmodule *obj = var_toobj(a);
bstring *attr = var_tostr(b);
bvalue tmp = *c; /* stack may change */
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;
if (be_module_setmember(vm, obj, attr, c)) {
dispatch();
} else {
// fall through exception below
}
}
attribute_error(vm, "writable attribute", a, b);
@ -1118,14 +1051,10 @@ newframe: /* a new call frame */
break;
}
case BE_MODULE: {
bmodule *f = var_toobj(var);
bvalue *member = be_module_attr(vm, f, str_literal(vm, "()"));
if (member && var_basetype(member) == BE_FUNCTION) {
*var = *member;
goto recall; /* call '()' method */
} else {
call_error(vm, var);
}
bvalue attr;
var_setstr(&attr, str_literal(vm, "()"));
module_attribute(vm, var, &attr, var); /* exception if not found */
goto recall; /* call '()' method */
break;
}
default:

View File

@ -4,18 +4,13 @@
-- description
--
-- a double dash ('--') start a line comment.
-- a: n means that the size of entity 'a' is 'n' bytes.
-- 'a: .n means that the size of entity 'a' is 'n' bits.
-- 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: 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](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 is equivalent to 'a:
-- b'.
-- N a number indicates the byte count of the field (eg. 'a: 1').
-- .N means the number of bits in the field (eg. 'a: .1').
-- only the first entity is a file entity (the root).
-------------------------------------------------------------------------------
@ -26,7 +21,7 @@ bytecode_file: -- little endian
header: 8
magic_number: 3 -- 0xbecdfe (berry code file)
version: 1 -- update with file structure definition
version: 2 -- update with file structure definition
integer_size: .1
float_size: .1
-- reserved space
@ -35,7 +30,7 @@ main_function -> function
global_desc:
builtin_count: 4
global_count: 4
global_count: 4 -- excluding builtins
global_name -> [
string
](global_count)
@ -48,7 +43,8 @@ function:
string
argc: 1 -- arguments count
nstack: 1 -- number of stack size by this function
extra: 2 -- extra data
varg: 1
extra: 1 -- extra data
bytecode:
code_size: 4
code_array -> [ -- bytecode array
@ -62,7 +58,7 @@ function:
[function](proto_count)
upval_table:
upval_count: 1
upvals -> [
upvals: [
instack: 1
index: 1
](upval_count)
@ -82,7 +78,7 @@ class:
string
member_count: 4 -- number of member variables
method_count: 4 -- number of method
method_table -> [
method_table: [
string -- method name
function -- method function body
](method_count)
@ -92,5 +88,5 @@ class:
nil: 1
boolean: 1
integer: 4 or 8
float: 4 or 8
integer: 4 | 8
float: 4 | 8

View File

@ -809,12 +809,10 @@ extern "C" {
// all good
be_return(vm);
} else {
be_return_nil(vm);
}
}
}
be_raise(vm, "attribute_error", "module 'lvgl' has no such attribute");
be_return_nil(vm);
}
/*********************************************************************************************\

View File

@ -57,9 +57,12 @@ extern "C" {
// we did have a match, low == high
be_pushint(vm, webserver_constants[constant_idx].value);
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);
}
}