diff --git a/lib/libesp32/berry/src/be_baselib.c b/lib/libesp32/berry/src/be_baselib.c index 2b9c25095..f556b4ab3 100644 --- a/lib/libesp32/berry/src/be_baselib.c +++ b/lib/libesp32/berry/src/be_baselib.c @@ -99,6 +99,25 @@ static bclass *find_class_closure(bclass *cl, bclosure *needle) return NULL; /* not found */ } +static bbool obj2int(bvm *vm, bvalue *var, bint *val) +{ + binstance *obj = var_toobj(var); + bstring *toint = str_literal(vm, "toint"); + /* get operator method */ + // TODO what if `tobool` is static + int type = be_instance_member(vm, obj, toint, vm->top); + if (type != BE_NONE && type != BE_NIL) { + vm->top[1] = *var; /* move self to argv[0] */ + be_dofunc(vm, vm->top, 1); /* call method 'tobool' */ + /* check the return value */ + if (var_isint(vm->top)) { + *val = var_toint(vm->top); + return btrue; + } + } + return bfalse; +} + static int l_super(bvm *vm) { int argc = be_top(vm); @@ -236,6 +255,15 @@ static int l_int(bvm *vm) } else if (be_iscomptr(vm, 1)) { intptr_t p = (intptr_t) be_tocomptr(vm, 1); be_pushint(vm, (int) p); + } else if (be_isinstance(vm, 1)) { + /* try to call `toint` method */ + bvalue *v = be_indexof(vm, 1); + bint val; + if (obj2int(vm, v, &val)) { + be_pushint(vm, val); + } else { + be_return_nil(vm); + } } else { be_return_nil(vm); } diff --git a/lib/libesp32/berry/src/be_vm.c b/lib/libesp32/berry/src/be_vm.c index 75c94d0fb..4a01b1de5 100644 --- a/lib/libesp32/berry/src/be_vm.c +++ b/lib/libesp32/berry/src/be_vm.c @@ -1248,6 +1248,18 @@ static void do_ntvfunc(bvm *vm, int pos, int argc) ret_native(vm); } +static void do_cfunc(bvm *vm, int pos, int argc) +{ + if (vm->ctypefunc) { + const void* args = var_toobj(vm->reg + pos); + push_native(vm, vm->reg + pos, argc, 0); + vm->ctypefunc(vm, args); + ret_native(vm); + } else { + vm_error(vm, "internal_error", "missing ctype_func handler"); + } +} + static void do_class(bvm *vm, int pos, int argc) { if (be_class_newobj(vm, var_toobj(vm->reg + pos), pos, ++argc, 0)) { @@ -1268,6 +1280,7 @@ void be_dofunc(bvm *vm, bvalue *v, int argc) case BE_CLOSURE: do_closure(vm, pos, argc); break; case BE_NTVCLOS: do_ntvclos(vm, pos, argc); break; case BE_NTVFUNC: do_ntvfunc(vm, pos, argc); break; + case BE_CTYPE_FUNC: do_cfunc(vm, pos, argc); break; default: call_error(vm, v); } }