diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 9ad02efa..2d273e46 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -34,10 +34,10 @@ void py_initialize(); void py_finalize(); /// Run a simple source string. Do not change the stack. -int py_exec(const char*); +bool py_exec(const char*); /// Eval a simple expression. /// The result will be set to `vm->last_retval`. -int py_eval(const char*); +bool py_eval(const char*); /************* Values Creation *************/ void py_newint(py_Ref, int64_t); @@ -90,7 +90,7 @@ double py_tofloat(const py_Ref); bool py_castfloat(const py_Ref, double* out); bool py_tobool(const py_Ref); const char* py_tostr(const py_Ref); -const char* py_tostrn(const py_Ref, int* out); +const char* py_tostrn(const py_Ref, int* size); void* py_touserdata(const py_Ref); @@ -100,8 +100,8 @@ void* py_touserdata(const py_Ref); #define py_isstr(self) py_istype(self, tp_str) bool py_istype(const py_Ref, py_Type); -// bool py_isinstance(const py_Ref obj, py_Type type); -// bool py_issubclass(py_Type derived, py_Type base); +bool py_isinstance(const py_Ref obj, py_Type type); +bool py_issubclass(py_Type derived, py_Type base); /************* References *************/ #define TypeError(x) false @@ -125,11 +125,20 @@ void py_bindmethod(py_Type type, const char* name, py_CFunction f); void py_bindmethod2(py_Type type, const char* name, py_CFunction f, BindType bt); void py_bindnativefunc(py_Ref obj, const char* name, py_CFunction f); +/// Get the reference to the i-th register. +/// @lifespan: Permanent. py_Ref py_reg(int i); +/// Get the reference of the object's `__dict__`. +/// The object must have a `__dict__`. +/// Returns a reference to the value or NULL if not found. +/// @lifespan: Object. py_Ref py_getdict(const py_Ref self, py_Name name); void py_setdict(py_Ref self, py_Name name, const py_Ref val); +/// Get the reference of the i-th slot of the object. +/// The object must have slots and `i` must be in range. +/// @lifespan: Object. py_Ref py_getslot(const py_Ref self, int i); void py_setslot(py_Ref self, int i, const py_Ref val); @@ -209,7 +218,10 @@ py_Error* py_lasterror(); void py_Error__print(py_Error*); /************* Operators *************/ -bool py_bool(const py_Ref); +/// Equivalent to `bool(val)`. +/// Returns 1 if `val` is truthy, otherwise 0. +/// Returns -1 if an error occurred. +int py_bool(const py_Ref val); int py_eq(const py_Ref, const py_Ref); int py_ne(const py_Ref, const py_Ref); diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index fe1ff0a2..a138ddb9 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -534,33 +534,43 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { /*****************************************/ case OP_JUMP_FORWARD: DISPATCH_JUMP((int16_t)byte.arg); case OP_POP_JUMP_IF_FALSE: { - bool res = py_bool(TOP()); + int res = py_bool(TOP()); + if(res < 0) goto __ERROR; POP(); if(!res) DISPATCH_JUMP((int16_t)byte.arg); DISPATCH(); } case OP_POP_JUMP_IF_TRUE: { - bool res = py_bool(TOP()); + int res = py_bool(TOP()); + if(res < 0) goto __ERROR; POP(); if(res) DISPATCH_JUMP((int16_t)byte.arg); DISPATCH(); } - case OP_JUMP_IF_TRUE_OR_POP: - if(py_bool(TOP())) { + case OP_JUMP_IF_TRUE_OR_POP: { + int res = py_bool(TOP()); + if(res < 0) goto __ERROR; + if(res) { DISPATCH_JUMP((int16_t)byte.arg); } else { POP(); DISPATCH(); } - case OP_JUMP_IF_FALSE_OR_POP: - if(!py_bool(TOP())) { + } + case OP_JUMP_IF_FALSE_OR_POP: { + int res = py_bool(TOP()); + if(res < 0) goto __ERROR; + if(!res) { DISPATCH_JUMP((int16_t)byte.arg); } else { POP(); DISPATCH(); } - case OP_SHORTCUT_IF_FALSE_OR_POP: - if(!py_bool(TOP())) { // [b, False] + } + case OP_SHORTCUT_IF_FALSE_OR_POP: { + int res = py_bool(TOP()); + if(res < 0) goto __ERROR; + if(!res) { // [b, False] STACK_SHRINK(2); // [] PUSH(&self->False); // [False] DISPATCH_JUMP((int16_t)byte.arg); @@ -568,6 +578,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { POP(); // [b] DISPATCH(); } + } case OP_LOOP_CONTINUE: // just an alias of OP_JUMP_FORWARD DISPATCH_JUMP((int16_t)byte.arg); diff --git a/src/public/cast.c b/src/public/cast.c index 2a949e28..c4f9d292 100644 --- a/src/public/cast.c +++ b/src/public/cast.c @@ -38,10 +38,10 @@ const char* py_tostr(const py_Ref self){ return py_Str__data(ud); } -const char* py_tostrn(const py_Ref self, int* out){ +const char* py_tostrn(const py_Ref self, int* size){ assert(self->type == tp_str); py_Str* ud = PyObject__value(self->_obj); - *out = ud->size; + *size = ud->size; return py_Str__data(ud); } diff --git a/src/public/py_ops.c b/src/public/py_ops.c index 7060c2be..326c3b6d 100644 --- a/src/public/py_ops.c +++ b/src/public/py_ops.c @@ -6,7 +6,7 @@ bool py_isidentical(const py_Ref lhs, const py_Ref rhs) { return false; } -bool py_bool(const py_Ref val) { return 0; } +int py_bool(const py_Ref val) { return 1; } bool py_hash(const py_Ref val, int64_t* out) { return 0; } diff --git a/src/public/vm.c b/src/public/vm.c index 1b3d56f6..07ce8b8b 100644 --- a/src/public/vm.c +++ b/src/public/vm.c @@ -23,15 +23,15 @@ void py_finalize() { pk_MemoryPools__finalize(); } -int py_exec(const char* source) { PK_UNREACHABLE(); } +bool py_exec(const char* source) { PK_UNREACHABLE(); } -int py_eval(const char* source) { +bool py_eval(const char* source) { CodeObject co; pk_SourceData_ src = pk_SourceData__rcnew(source, "main.py", EVAL_MODE, false); Error* err = pk_compile(src, &co); if(err) { PK_DECREF(src); - return -1; + return false; } pk_VM* vm = pk_current_vm; Frame* frame = Frame__new(&co, &vm->main, NULL, vm->stack.sp, vm->stack.sp, &co); @@ -39,8 +39,8 @@ int py_eval(const char* source) { pk_FrameResult res = pk_VM__run_top_frame(vm); CodeObject__dtor(&co); PK_DECREF(src); - if(res == RES_ERROR) return vm->last_error->type; - if(res == RES_RETURN) return 0; + if(res == RES_ERROR) return false; + if(res == RES_RETURN) return true; PK_UNREACHABLE(); } diff --git a/src2/main.c b/src2/main.c index c976f242..d50f1c47 100644 --- a/src2/main.c +++ b/src2/main.c @@ -29,9 +29,6 @@ int main(int argc, char** argv) { const char* source = "1 < 2"; if(py_eval(source)) { - py_Error* err = py_lasterror(); - py_Error__print(err); - } else { // handle the result bool _L0 = py_tobool(py_lastretval()); printf("%d\n", _L0);