diff --git a/lib/libesp32/Berry/src/be_class.c b/lib/libesp32/Berry/src/be_class.c index 68643167a..280e3e6d0 100644 --- a/lib/libesp32/Berry/src/be_class.c +++ b/lib/libesp32/Berry/src/be_class.c @@ -184,13 +184,14 @@ static binstance* newobject(bvm *vm, bclass *c) return obj; } -bbool be_class_newobj(bvm *vm, bclass *c, bvalue *reg, int argc) +bbool be_class_newobj(bvm *vm, bclass *c, bvalue *reg, int argc, int mode) { bvalue init; size_t pos = reg - vm->reg; binstance *obj = newobject(vm, c); - reg = vm->reg + pos; /* the stack may have changed */ + reg = vm->reg + pos - mode; /* the stack may have changed */ var_setinstance(reg, obj); + var_setinstance(reg + mode, obj); /* find constructor */ obj = instance_member(vm, obj, str_literal(vm, "init"), &init); if (obj && var_type(&init) != MT_VARIABLE) { diff --git a/lib/libesp32/Berry/src/be_class.h b/lib/libesp32/Berry/src/be_class.h index 34be6943a..148f1b57a 100644 --- a/lib/libesp32/Berry/src/be_class.h +++ b/lib/libesp32/Berry/src/be_class.h @@ -55,7 +55,7 @@ void be_prim_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f); void be_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl); int be_class_closure_count(bclass *c); void be_class_upvalue_init(bvm *vm, bclass *c); -bbool be_class_newobj(bvm *vm, bclass *c, bvalue *argv, int argc); +bbool be_class_newobj(bvm *vm, bclass *c, bvalue *argv, int argc, int mode); int be_instance_member(bvm *vm, binstance *obj, bstring *name, bvalue *dst); bbool be_instance_setmember(bvm *vm, binstance *obj, bstring *name, bvalue *src); diff --git a/lib/libesp32/Berry/src/be_vm.c b/lib/libesp32/Berry/src/be_vm.c index 791c9a529..b58da91d9 100644 --- a/lib/libesp32/Berry/src/be_vm.c +++ b/lib/libesp32/Berry/src/be_vm.c @@ -990,8 +990,9 @@ newframe: /* a new call frame */ ++var, --argc, mode = 1; goto recall; case BE_CLASS: - if (be_class_newobj(vm, var_toobj(var), var, ++argc)) { - reg = vm->reg; + if (be_class_newobj(vm, var_toobj(var), var, ++argc, mode)) { + reg = vm->reg + mode; + mode = 0; var = RA() + 1; /* to next register */ goto recall; /* call constructor */ } @@ -1109,7 +1110,7 @@ static void do_ntvfunc(bvm *vm, bvalue *reg, int argc) static void do_class(bvm *vm, bvalue *reg, int argc) { - if (be_class_newobj(vm, var_toobj(reg), reg, ++argc)) { + if (be_class_newobj(vm, var_toobj(reg), reg, ++argc, 0)) { be_incrtop(vm); be_dofunc(vm, reg + 1, argc); be_stackpop(vm, 1); diff --git a/lib/libesp32/Berry/tests/class.be b/lib/libesp32/Berry/tests/class.be index fb310e802..8c194a175 100644 --- a/lib/libesp32/Berry/tests/class.be +++ b/lib/libesp32/Berry/tests/class.be @@ -20,3 +20,28 @@ for i : Test(10) sum += i end assert(sum == 55, 'iteraion sum is ' + str(sum) + ' (expected 55).') + +#- test case for class instanciated from module member #103 -# + +m = module() +g_i = 0 #- detect side effect from init() -# +class C def init() g_i += 1 end end +m.C = C + +#- normal invocation -# +assert(type(C()) == 'instance') +assert(g_i == 1) + +#- invoke from module member -# +assert(type(m.C()) == 'instance') +assert(g_i == 2) + +class C2 var C1 def init(c) self.C1 = c end end +m.C2 = C2 +c2 = m.C2(m.C) + +assert(c2.C1 == C) + +c3 = m.C2(m.C()) +assert(type(c3.C1) == 'instance') +assert(classname(c3.C1) == 'C')