diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 1a280992..afe73746 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -208,12 +208,14 @@ bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop); void py_assign(py_Ref dst, const py_Ref src); /************* Stack Operations *************/ -/// Returns a reference to the i-th object from the top of the stack. +/// Return a reference to the i-th object from the top of the stack. /// i should be negative, e.g. (-1) means TOS. py_StackRef py_peek(int i); -/// Pushes the object to the stack. +/// Push the object to the stack. void py_push(const py_Ref src); -/// Pops an object from the stack. +/// Push a nil object to the stack. +void py_pushnil(); +/// Pop an object from the stack. void py_pop(); /// Shrink the stack by n. void py_shrink(int n); diff --git a/include/pocketpy/xmacros/magics.h b/include/pocketpy/xmacros/magics.h index ac679f0b..a43d17b1 100644 --- a/include/pocketpy/xmacros/magics.h +++ b/include/pocketpy/xmacros/magics.h @@ -9,6 +9,7 @@ MAGIC_METHOD(__iter__) MAGIC_METHOD(__next__) MAGIC_METHOD(__neg__) MAGIC_METHOD(__invert__) +MAGIC_METHOD(__bool__) // logical operators MAGIC_METHOD(__contains__) ///////////////////////////// diff --git a/src/public/py_ops.c b/src/public/py_ops.c index 9e6c298d..9c1f6bc9 100644 --- a/src/public/py_ops.c +++ b/src/public/py_ops.c @@ -4,7 +4,7 @@ bool py_isidentical(const py_Ref lhs, const py_Ref rhs) { if(lhs->type != rhs->type) return false; - switch(lhs->type){ + switch(lhs->type) { case tp_int: return lhs->_i64 == rhs->_i64; case tp_float: return lhs->_f64 == rhs->_f64; case tp_bool: return lhs->_bool == rhs->_bool; @@ -14,10 +14,34 @@ bool py_isidentical(const py_Ref lhs, const py_Ref rhs) { case tp_ellipsis: return true; // fallback to pointer comparison default: return lhs->is_ptr && rhs->is_ptr && lhs->_obj == rhs->_obj; - } + } } -int py_bool(const py_Ref val) { return 1; } +int py_bool(const py_Ref val) { + switch(val->type) { + case tp_bool: return val->_bool; + case tp_int: return val->_i64 != 0; + case tp_float: return val->_f64 != 0; + case tp_none_type: return 0; + default: { + py_Ref tmp = py_tpfindmagic(val->type, __bool__); + if(tmp) { + bool ok = py_call(tmp, 1, val); + if(!ok) return -1; + return py_tobool(py_retval()); + } else { + tmp = py_tpfindmagic(val->type, __len__); + if(tmp) { + bool ok = py_call(tmp, 1, val); + if(!ok) return -1; + return py_toint(py_retval()); + } else { + return 1; // True + } + } + } + } +} bool py_hash(const py_Ref val, int64_t* out) { return 0; } @@ -37,7 +61,7 @@ bool py_delitem(py_Ref self, const py_Ref key) { return -1; } int py_##name(const py_Ref lhs, const py_Ref rhs) { \ bool ok = py_binaryop(lhs, rhs, op, rop); \ if(!ok) return -1; \ - return py_tobool(py_retval()); \ + return py_tobool(py_retval()); \ } COMPARE_OP_IMPL(eq, __eq__, __eq__) diff --git a/src/public/stack_ops.c b/src/public/stack_ops.c index 2bc6686d..adb9581d 100644 --- a/src/public/stack_ops.c +++ b/src/public/stack_ops.c @@ -64,6 +64,11 @@ void py_push(const py_Ref src){ *vm->stack.sp++ = *src; } +void py_pushnil(){ + pk_VM* vm = pk_current_vm; + py_newnil(vm->stack.sp++); +} + py_Ref py_pushtmp(){ pk_VM* vm = pk_current_vm; py_newnil(vm->stack.sp++); diff --git a/src/public/vm.c b/src/public/vm.c index f6321900..656ccabd 100644 --- a/src/public/vm.c +++ b/src/public/vm.c @@ -184,11 +184,22 @@ bool py_exec(const char* source) { return pk_VM__exec(pk_current_vm, source, "", EVAL_MODE); } -bool py_exec2(const char* source, const char* filename, enum CompileMode mode){ +bool py_exec2(const char* source, const char* filename, enum CompileMode mode) { return pk_VM__exec(pk_current_vm, source, filename, mode); } -bool py_call(py_Ref f, int argc, py_Ref argv) { return -1; } +bool py_call(py_Ref f, int argc, py_Ref argv) { + if(f->type == tp_nativefunc) { + return f->_cfunc(argc, argv); + } else { + pk_VM* vm = pk_current_vm; + py_push(f); + py_pushnil(); + for(int i = 0; i < argc; i++) + py_push(py_offset(argv, i)); + return pk_VM__vectorcall(vm, argc, 0, false) == RES_ERROR; + } +} bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; } @@ -285,9 +296,6 @@ bool py_callmagic(py_Name name, int argc, py_Ref argv) { assert(argc >= 1); assert(py_ismagicname(name)); py_Ref tmp = py_tpfindmagic(argv->type, name); - if(!tmp){ - return AttributeError(argv, name); - } - if(tmp->type == tp_nativefunc) return tmp->_cfunc(argc, argv); + if(!tmp) return AttributeError(argv, name); return py_call(tmp, argc, argv); }